Load all of the throw
data
# load omnibus dataframe
omnibus_df <- read_delim("../data/processed/omnibus/omnibus_raw.csv",
delim = ",",
col_types = cols(
.default = col_double(),
type = col_factor(),
ppid = col_factor(),
exp_label = col_factor(),
experiment = col_factor(),
hand = col_factor(),
camera_tilt = col_factor(),
surface_tilt = col_factor(),
target = col_factor(),
test_type = col_factor(),
prior_anim = col_factor(),
baseline_block = col_factor(),
task_type = col_factor(),
surface = col_factor(),
anim_type = col_factor()
)
) %>% # filter out practice blocks
filter(block_num > 4)
# Optionally make learning rate summaries
# do the following if learning_rate_df.csv doesn't exist in ../data/processed
# This takes a loong time
if (!file.exists("../data/processed/learning_rate_df.csv")) {
print(Sys.time())
apply_exponentialFit <- function(df) {
df %>%
summarise(
ppid = first(ppid),
experiment = first(experiment),
test_type = first(test_type),
exponentialFit = exponentialFit2(norm_throw_deviation, mode = test_type[1])
)
}
block_init_learning_rates <- omnibus_df %>%
filter(str_detect(test_type, "init")) %>%
group_by(ppid, experiment, test_type) %>%
group_split() %>%
future_map(apply_exponentialFit) %>%
bind_rows() %>%
unnest(cols = c("exponentialFit"))
print("done")
print(Sys.time())
write_csv(block_init_learning_rates, "../data/processed/learning_rate_df.csv")
} else {
print("learning_rate_df.csv exists, loading from file")
block_init_learning_rates <- read_csv("../data/processed/learning_rate_df.csv",
col_types = cols(
.default = col_double(),
experiment = col_factor(),
test_type = col_factor()
)
)
}
[1] "learning_rate_df.csv exists, loading from file"
Visualizing data
(univariate)
Vectors representing the throw velocity (trace 0) and the velocity
applied to the ball (trace 1). The y dimention of the throw is
essentially ignored (in reality there is a slight tilt added to account
for the tilt of the surface).
test_ppt <- 3
test_df <- omnibus_df %>% filter(ppid == test_ppt)
trial <- 250
trial_df <- filter(test_df, trial_num == trial)
x <- trial_df$flick_velocity_x
y <- trial_df$flick_velocity_y
z <- trial_df$flick_velocity_z
x2 <- trial_df$flick_direction_x * -1
y2 <- trial_df$flick_direction_y * -1
z2 <- trial_df$flick_direction_z * -1
# plot both
p <- plot_ly(x = c(0, x), y = c(0, y), z = c(0, z), type = "scatter3d", mode = "lines") %>%
add_trace(x = c(0, x2), y = c(0, y2), z = c(0, z2), type = "scatter3d", mode = "lines") %>%
layout(scene = list(
xaxis = list(title = "x", range = c(-2, 2)),
yaxis = list(title = "y", range = c(-1, 3)),
zaxis = list(title = "z", range = c(-1, 3)),
aspectmode = "cube" # equal aspect ratios
))
# Render the plot
p
note: this is a rotated trial
Distribution of
errors
# plot distribution of error_size
p <- ggplot(omnibus_df, aes(
x = error_size,
fill = type
)) +
geom_histogram(binwidth = .5, alpha = .6) +
theme_minimal() +
theme(text = element_text(size = 11)) +
scale_fill_manual(values = c("#f9982c", "#d40000")) +
labs(x = "Error Size (cm)", y = "Count")
p

Distribution of
throw angles
# plot distribution of error_size
p <- ggplot(omnibus_df, aes(
x = throw_deviation,
fill = type
)) +
geom_histogram(binwidth = 1, alpha = .6) +
theme_minimal() +
theme(text = element_text(size = 11)) +
scale_fill_manual(values = c("#f9982c", "#d40000")) +
labs(
x = "Throw Angle (°)", y = "Count"
) + # dashed lines at 0, -15, -30
geom_vline(
xintercept = c(0, -15, -30), linewidth = 0.4,
colour = "#CCCCCC", linetype = "dashed"
) + # ticks of 15 degrees
scale_x_continuous(
breaks = c(-30, 0, 30, -60, -90)
)
p

Original
Experiments
Plot ANGULAR
DEVIATIONS (hand angles)
Note: Blues = Acceleration Perturbations
# rest of the exps
data_per_group <- omnibus_df %>%
filter(exp_label == "original_exps" | exp_label == "curved_path") %>%
group_by(experiment, test_type, trial_num) %>%
summarise(
mean_deviation = mean(throw_deviation),
ci_deviation = vector_confint(throw_deviation),
.groups = "drop"
)
# set up plot
p <- data_per_group %>%
ggplot(
aes(
x = trial_num, y = mean_deviation, colour = experiment
)
) +
theme_classic() +
# theme(legend.position = "none") +
labs(
x = "Trial Number",
y = "Throw Angle (°)"
)
# add horizontal lines
p <- p +
geom_hline(
yintercept = c(0, -30), linewidth = 0.4,
colour = "#CCCCCC", linetype = "solid"
) +
geom_hline(
yintercept = c(-15), linewidth = 0.4,
colour = "#CCCCCC", linetype = "dashed"
)
# p <- p +
# scale_y_continuous(
# limits = c(-10, 35),
# breaks = c(0, 15, 30),
# labels = c(0, 15, 30)
# ) +
# scale_x_continuous(
# limits = c(0, 180),
# breaks = c(0, 60, 120, 180),
# labels = c(0, 60, 120, 180)
# )
# set font size to 11
p <- p +
theme(text = element_text(size = 11))
# add confidence intervals and data points
p <- p + geom_ribbon(
aes(
ymin = mean_deviation - ci_deviation,
ymax = mean_deviation + ci_deviation,
fill = experiment
),
colour = NA, alpha = 0.3
) + geom_line()
# set colour palette
p <- p +
scale_colour_manual(values = pallete_list) +
scale_fill_manual(values = pallete_list)
# # save
# if (save_plots) {
# ggsave(
# p,
# filename = "../plots/paper_figs/sr_30_training.pdf", device = "pdf",
# height = 4, width = 6
# )
# }
ggplotly(p)
# p
Trial sets of
interest only
Note: Blues = Acceleration Perturbations
# filter out just the trials of interest
data_per_group <- data_per_group %>%
filter(
test_type != "other"
)
# add a dummy column with repeating sequence
# NOTE: this can't be combined with above since we are using nrow
data_per_group <- data_per_group %>%
mutate(dummy_x = rep(1:(nrow(data_per_group) / NUM_EXPS),
length.out = nrow(data_per_group)
))
# set up plot
p <- data_per_group %>%
ggplot(
aes(
x = dummy_x, y = mean_deviation, colour = experiment
)
) +
theme_classic() +
# theme(legend.position = "none") +
labs(
x = "Trial Number",
y = "Throw Angle (°)"
)
# add horizontal lines
p <- p +
geom_hline(
yintercept = c(0, -30), linewidth = 0.4,
colour = "#CCCCCC", linetype = "solid"
) +
geom_hline(
yintercept = c(-15), linewidth = 0.4,
colour = "#CCCCCC", linetype = "dashed"
)
# add confidence intervals and data points
for (unique_test_type in unique(data_per_group$test_type)) {
# get the data for this block
to_plot_data <- filter(data_per_group, test_type == unique_test_type)
p <- p + geom_ribbon(
data = to_plot_data,
aes(
ymin = mean_deviation - ci_deviation,
ymax = mean_deviation + ci_deviation,
fill = experiment
), colour = NA, alpha = 0.3
) + geom_line(
data = to_plot_data
)
}
# set colour palette
p <- p +
scale_colour_manual(values = pallete_list) +
scale_fill_manual(values = pallete_list)
ggplotly(p)
Plot NORMALIZED
ANGULAR DEVIATIONS (hand angles)
Note: Blues = Acceleration Perturbations
# rest of the exps
data_per_group <- omnibus_df %>%
filter(exp_label == "original_exps" | exp_label == "curved_path") %>%
group_by(experiment, test_type, trial_num) %>%
summarise(
mean_deviation = mean(norm_throw_deviation),
ci_deviation = vector_confint(norm_throw_deviation),
.groups = "drop"
)
# set up plot
p <- data_per_group %>%
ggplot(
aes(
x = trial_num, y = mean_deviation, colour = experiment
)
) +
theme_classic() +
# theme(legend.position = "none") +
labs(
x = "Trial Number",
y = "Normalized Throw Angle"
)
# add horizontal lines
p <- p +
geom_hline(
yintercept = c(0, 1, 2), linewidth = 0.4,
colour = "#CCCCCC", linetype = "solid"
) +
geom_hline(
yintercept = c(0.5, 1.5), linewidth = 0.4,
colour = "#CCCCCC", linetype = "dashed"
)
# p <- p +
# scale_y_continuous(
# limits = c(-10, 35),
# breaks = c(0, 15, 30),
# labels = c(0, 15, 30)
# ) +
# scale_x_continuous(
# limits = c(0, 180),
# breaks = c(0, 60, 120, 180),
# labels = c(0, 60, 120, 180)
# )
# set font size to 11
p <- p +
theme(text = element_text(size = 11))
# add confidence intervals and data points
p <- p + geom_ribbon(
aes(
ymin = mean_deviation - ci_deviation,
ymax = mean_deviation + ci_deviation,
fill = experiment
),
colour = NA, alpha = 0.3
) + geom_line()
# set colour palette
p <- p +
scale_colour_manual(values = pallete_list) +
scale_fill_manual(values = pallete_list)
# # save
# if (save_plots) {
# ggsave(
# p,
# filename = "../plots/paper_figs/sr_30_training.pdf", device = "pdf",
# height = 4, width = 6
# )
# }
ggplotly(p)
# p
Trial sets of
interest only
Note: Blues = Acceleration Perturbations
# filter out just the trials of interest
data_per_group <- data_per_group %>%
filter(
test_type != "other"
)
# add a dummy column with repeating sequence
# NOTE: this can't be combined with above since we are using nrow
data_per_group <- data_per_group %>%
mutate(dummy_x = rep(1:(nrow(data_per_group) / NUM_EXPS),
length.out = nrow(data_per_group)
))
# set up plot
p <- data_per_group %>%
ggplot(
aes(
x = dummy_x, y = mean_deviation, colour = experiment
)
) +
theme_classic() +
# theme(legend.position = "none") +
labs(
x = "Trial Number",
y = "Normalized Throw Angle"
)
# add horizontal lines
p <- p +
geom_hline(
yintercept = c(0, 1, 2), linewidth = 0.4,
colour = "#CCCCCC", linetype = "solid"
) +
geom_hline(
yintercept = c(0.5, 1.5), linewidth = 0.4,
colour = "#CCCCCC", linetype = "dashed"
)
# add confidence intervals and data points
for (unique_test_type in unique(data_per_group$test_type)) {
# get the data for this block
to_plot_data <- filter(data_per_group, test_type == unique_test_type)
p <- p + geom_ribbon(
data = to_plot_data,
aes(
ymin = mean_deviation - ci_deviation,
ymax = mean_deviation + ci_deviation,
fill = experiment
), colour = NA, alpha = 0.3
) + geom_line(
data = to_plot_data
)
}
# set colour palette
p <- p +
scale_colour_manual(values = pallete_list) +
scale_fill_manual(values = pallete_list)
ggplotly(p)
Learning Rates, Start
Points and Asymptotes
Learning Rates
data_ppt <- block_init_learning_rates %>%
filter(experiment != "a_ball_roll_animate_surface")
data_group <- data_ppt %>%
group_by(experiment, test_type) %>%
summarise(
mean_learning_rate = mean(exp_fit_lambda),
ci_learning_rate = vector_confint(exp_fit_lambda),
mean_high = mean(exp_fit_N0),
ci_high = vector_confint(exp_fit_N0),
mean_low = mean(exp_fit_displace),
ci_low = vector_confint(exp_fit_displace),
.groups = "drop"
)
p <- data_group %>%
ggplot(
aes(x = experiment, y = mean_learning_rate, colour = experiment)
) +
theme_classic() +
labs(
x = NULL,
y = "Learning Rate"
) +
facet_wrap(~test_type)
# remove all x axis labels
p <- p + theme(axis.text.x = element_blank())
# for the colour legend, only show the first 7 Note this doesn't work for the plotly plot
p <- p + guides(colour = guide_legend(override.aes = list(alpha = 1)))
# add data points
p <- p +
geom_beeswarm(
data = data_ppt,
aes(
y = exp_fit_lambda
),
alpha = 0.1,
size = 1
) +
geom_linerange(aes(
ymin = mean_learning_rate - ci_learning_rate,
ymax = mean_learning_rate + ci_learning_rate
), alpha = 0.5, lwd = 2) +
geom_point()
# set colour palette
p <- p +
scale_colour_manual(values = pallete_list) +
scale_fill_manual(values = pallete_list)
ggplotly(p)
# p
High Points
(Asymptotes or Starts)
p <- data_group %>%
ggplot(
aes(x = experiment, y = mean_high, colour = experiment)
) +
theme_classic() +
labs(
x = NULL,
y = "High Point"
) +
facet_wrap(~test_type)
# remove all x axis labels
p <- p + theme(axis.text.x = element_blank())
# for the colour legend, only show the first 7 Note this doesn't work for the plotly plot
p <- p + guides(colour = guide_legend(override.aes = list(alpha = 1)))
# add data points
p <- p +
geom_beeswarm(
data = data_ppt,
aes(
y = exp_fit_N0
),
alpha = 0.1,
size = 1
) +
geom_linerange(aes(
ymin = mean_high - ci_high,
ymax = mean_high + ci_high
), alpha = 0.5, lwd = 2) +
geom_point()
# set colour palette
p <- p +
scale_colour_manual(values = pallete_list) +
scale_fill_manual(values = pallete_list)
ggplotly(p)
# p
Low Points
(Asymptotes or Starts)
p <- data_group %>%
ggplot(
aes(x = experiment, y = mean_low, colour = experiment)
) +
theme_classic() +
labs(
x = NULL,
y = "Low Point"
) +
facet_wrap(~test_type)
# remove all x axis labels
p <- p + theme(axis.text.x = element_blank())
# for the colour legend, only show the first 7 Note this doesn't work for the plotly plot
p <- p + guides(colour = guide_legend(override.aes = list(alpha = 1)))
# add data points
p <- p +
geom_beeswarm(
data = data_ppt,
aes(
y = exp_fit_displace
),
alpha = 0.1,
size = 1
) +
geom_linerange(aes(
ymin = mean_low - ci_low,
ymax = mean_low + ci_low
), alpha = 0.5, lwd = 2) +
geom_point()
# set colour palette
p <- p +
scale_colour_manual(values = pallete_list) +
scale_fill_manual(values = pallete_list)
ggplotly(p)
# p
For washout: The CUED accel + curved have a lower starting point
(therefore – cue works). VMR group has slightly lower. When comparing
everything with a high starting point, the ACCEL group has a much FASTER
learning rate. When transferring, no difference in learning rates.
# Compare learning rates and high points
p <- data_ppt %>%
ggplot(
aes(x = exp_fit_lambda, y = exp_fit_N0, colour = experiment)
) +
theme_classic() +
labs(
x = "Learning Rate",
y = "High Point"
) +
facet_wrap(~test_type) +
geom_point() +
scale_colour_manual(values = pallete_list) +
scale_fill_manual(values = pallete_list)
ggplotly(p)
Correlations within
the 3 variables above
# 3d plot of learning rates, high points, and low points
# filter out just the washout trials for now
data_ppt <- block_init_learning_rates %>%
filter(test_type == "washout_init")
p <- plot_ly(type = "scatter3d", mode = "markers")
for (experiment_ in unique(data_ppt$experiment)) {
# get the data for this block
to_plot_data <- filter(data_ppt, experiment == experiment_)
p <- p %>%
add_trace(
x = to_plot_data$exp_fit_lambda,
y = to_plot_data$exp_fit_N0,
z = to_plot_data$exp_fit_displace,
color = I(pallete_list[experiment_]),
name = experiment_
)
}
# Axes names
p <- p %>% layout(
scene =
(list(
xaxis = list(title = "Learning Rate"),
yaxis = list(title = "High Point"),
zaxis = list(title = "Low Point"),
aspectmode = "cube" # equal aspect ratios
))
)
p
- We might want to test if data points cluster differently depending
on the experiment conditions.
- Note: It is a good idea to do some EDA to check if all 3 dimensions
are required. Correlation matrix?
### TESTING
# rest of the exps
data_ <- omnibus_df %>%
filter(experiment == "accel_uncued", test_type == "washout_init")
# set up plot
p <- data_ %>%
ggplot(
aes(
x = trial_num, y = norm_throw_deviation, colour = ppid
)
) +
theme_classic() +
# theme(legend.position = "none") +
labs(
x = "Trial Number",
y = "Normalized Throw Angle"
)
# add horizontal lines
p <- p +
geom_hline(
yintercept = c(0, 1, 2), linewidth = 0.4,
colour = "#CCCCCC", linetype = "solid"
) +
geom_hline(
yintercept = c(0.5, 1.5), linewidth = 0.4,
colour = "#CCCCCC", linetype = "dashed"
)
# p <- p +
# scale_y_continuous(
# limits = c(-10, 35),
# breaks = c(0, 15, 30),
# labels = c(0, 15, 30)
# ) +
# scale_x_continuous(
# limits = c(0, 180),
# breaks = c(0, 60, 120, 180),
# labels = c(0, 60, 120, 180)
# )
# set font size to 11
p <- p +
theme(text = element_text(size = 11))
# add confidence intervals and data points
p <- p + geom_line()
# # save
# if (save_plots) {
# ggsave(
# p,
# filename = "../plots/paper_figs/sr_30_training.pdf", device = "pdf",
# height = 4, width = 6
# )
# }
ggplotly(p)
# p
Plot ERROR SIZE
Note: Blues = Acceleration Perturbations
# original experiments only
data_per_group <- omnibus_df %>%
filter(exp_label == "original_exps" | exp_label == "curved_path") %>%
group_by(experiment, test_type, trial_num) %>%
summarise(
mean_deviation = mean(error_size),
ci_deviation = vector_confint(error_size),
.groups = "drop"
)
# set up plot
p <- data_per_group %>%
ggplot(
aes(
x = trial_num, y = mean_deviation, colour = experiment
)
) +
theme_classic() +
# theme(legend.position = "none") +
labs(
x = "Trial Number",
y = "Absolute Target Error (cm)"
)
# add horizontal lines
p <- p +
geom_hline(
yintercept = c(0, 40), linewidth = 0.4,
colour = "#CCCCCC", linetype = "solid"
) +
geom_hline(
yintercept = c(20), linewidth = 0.4,
colour = "#CCCCCC", linetype = "dashed"
)
# p <- p +
# scale_y_continuous(
# limits = c(-10, 35),
# breaks = c(0, 15, 30),
# labels = c(0, 15, 30)
# ) +
# scale_x_continuous(
# limits = c(0, 180),
# breaks = c(0, 60, 120, 180),
# labels = c(0, 60, 120, 180)
# )
# set font size to 11
p <- p +
theme(text = element_text(size = 11))
# add confidence intervals and data points
p <- p + geom_ribbon(
aes(
ymin = mean_deviation - ci_deviation,
ymax = mean_deviation + ci_deviation,
fill = experiment
),
colour = NA, alpha = 0.3
) + geom_line()
# set colour palette
p <- p +
scale_colour_manual(values = pallete_list) +
scale_fill_manual(values = pallete_list)
# # save
# if (save_plots) {
# ggsave(
# p,
# filename = "../plots/paper_figs/sr_30_training.pdf", device = "pdf",
# height = 4, width = 6
# )
# }
ggplotly(p)
# p
visible vs non-visible tilt doesn’t affect the 15-degree rotation
condition. But affects all other conditions. So 15-degree rotation
Trial sets of
interest only
Note: Blues = Acceleration Perturbations
# filter out just the trials of interest
data_per_group <- data_per_group %>%
filter(
test_type != "other"
)
# add a dummy column with repeating sequence
# NOTE: this can't be combined with above since we are using nrow
data_per_group <- data_per_group %>%
mutate(dummy_x = rep(1:(nrow(data_per_group) / NUM_EXPS),
length.out = nrow(data_per_group)
))
# set up plot
p <- data_per_group %>%
ggplot(
aes(
x = dummy_x, y = mean_deviation, colour = experiment
)
) +
theme_classic() +
# theme(legend.position = "none") +
labs(
x = "Trial Number",
y = "Absolute Target Error (cm)"
)
# add horizontal lines
p <- p +
geom_hline(
yintercept = c(0, 40), linewidth = 0.4,
colour = "#CCCCCC", linetype = "solid"
) +
geom_hline(
yintercept = c(20), linewidth = 0.4,
colour = "#CCCCCC", linetype = "dashed"
)
# add confidence intervals and data points
for (unique_test_type in unique(data_per_group$test_type)) {
# get the data for this block
to_plot_data <- filter(data_per_group, test_type == unique_test_type)
p <- p + geom_ribbon(
data = to_plot_data,
aes(
ymin = mean_deviation - ci_deviation,
ymax = mean_deviation + ci_deviation,
fill = experiment
), colour = NA, alpha = 0.3
) + geom_line(
data = to_plot_data
)
}
# set colour palette
p <- p +
scale_colour_manual(values = pallete_list) +
scale_fill_manual(values = pallete_list)
ggplotly(p)
Animated Surface
Follow-up
Plot ANGULAR
DEVIATIONS (hand angles)
# isolate animate_surface exp
data_per_group <- omnibus_df %>%
filter(exp_label == "animate_surface") %>%
group_by(prior_anim, block_num, trial_num_in_block, trial_num) %>%
summarise(
mean_deviation = mean(throw_deviation),
ci_deviation = vector_confint(throw_deviation)
)
# order the factors for assigning colour pallets
data_per_group$prior_anim <- factor(
data_per_group$prior_anim,
levels = c(
"none", "half_anim", "full_anim"
)
)
# set up plot
p <- data_per_group %>%
ggplot(
aes(
x = trial_num, y = mean_deviation,
ymin = mean_deviation - ci_deviation,
ymax = mean_deviation + ci_deviation
)
) +
theme_classic() +
# theme(legend.position = "none") +
labs(
x = "Trial Number",
y = "Throw Angle (°)"
)
# add horizontal lines
p <- p +
geom_hline(
yintercept = c(0, -30), linewidth = 0.4,
colour = "#CCCCCC", linetype = "solid"
) +
geom_hline(
yintercept = c(-15), linewidth = 0.4,
colour = "#CCCCCC", linetype = "dashed"
)
# p <- p +
# scale_y_continuous(
# limits = c(-10, 35),
# breaks = c(0, 15, 30),
# labels = c(0, 15, 30)
# ) +
# scale_x_continuous(
# limits = c(0, 180),
# breaks = c(0, 60, 120, 180),
# labels = c(0, 60, 120, 180)
# )
# set font size to 11
p <- p +
theme(text = element_text(size = 11))
# repeat for prior_anim == "half", "full" and "wait"
for (unique_prior_anim in unique(data_per_group$prior_anim)) {
# get the data for this block
to_plot_data <- filter(data_per_group, prior_anim == unique_prior_anim)
# loop through the unique blocks in to_plot_data
for (block in unique(to_plot_data$block_num)) {
# get the data for this block
block_data <- filter(to_plot_data, block_num == block)
# add the data, use the pallete_list to get the colour
p <- p + geom_ribbon(
data = block_data,
aes(fill = prior_anim),
colour = NA, alpha = 0.3
) + geom_line(
data = block_data,
aes(colour = prior_anim)
)
}
}
# set colour palette
p <- p +
scale_colour_manual(values = pallete_list) +
scale_fill_manual(values = pallete_list)
# # save
# if (save_plots) {
# ggsave(
# p,
# filename = "../plots/paper_figs/sr_30_training.pdf", device = "pdf",
# height = 4, width = 6
# )
# }
ggplotly(p)
# p
Washout trials
after half VS full animations
# first, isolate the data
data <- omnibus_df %>%
filter(
exp_label == "animate_surface",
baseline_block == FALSE,
test_type == "washout_anim"
)
data_per_ppt <- data %>%
group_by(ppid, prior_anim, trial_num_in_block) %>%
summarise(
ppt_mean_deviation = median(throw_deviation),
ppt_ci_deviation = vector_confint(throw_deviation),
n = n()
)
data_per_group <- data_per_ppt %>%
group_by(prior_anim, trial_num_in_block) %>%
summarise(
mean_deviation = mean(ppt_mean_deviation),
ci_deviation = vector_confint(ppt_mean_deviation),
n = sum(n)
)
# set up plot
p <- data_per_group %>%
ggplot(
aes(
x = trial_num_in_block, y = mean_deviation,
colour = prior_anim, fill = prior_anim
)
) +
theme_classic() +
# theme(legend.position = "none") +
labs(
x = "Trial Number in Block",
y = "Throw Angle (°)"
)
# add horizontal lines
p <- p +
geom_hline(
yintercept = c(0, -30), linewidth = 0.4,
colour = "#CCCCCC", linetype = "solid"
) +
geom_hline(
yintercept = c(-15), linewidth = 0.4,
colour = "#CCCCCC", linetype = "dashed"
)
# add data points
p <- p + geom_beeswarm(
data = data_per_ppt,
aes(
y = ppt_mean_deviation,
colour = prior_anim
),
size = 1, dodge.width = 0.5
) + geom_ribbon(
aes(
ymin = mean_deviation - ci_deviation,
ymax = mean_deviation + ci_deviation
),
colour = NA, alpha = 0.3
) + geom_line()
# add washout_init from the 30-degree rotation condition
data_per_ppt_30 <- omnibus_df %>%
filter(
experiment %in% c("rot30_cued_tilt", "rot30_uncued"),
test_type == "washout_init"
) %>% # rename the experiment column to prior_anim
mutate(prior_anim = experiment)
data_per_group_30 <- data_per_ppt_30 %>%
group_by(prior_anim, trial_num_in_block) %>%
summarise(
mean_deviation = mean(throw_deviation),
ci_deviation = vector_confint(throw_deviation),
n = n()
)
# add data points
p <- p + geom_beeswarm(
data = data_per_ppt_30,
aes(
y = throw_deviation,
colour = prior_anim
),
size = 1, dodge.width = 0.5
) + geom_ribbon(
data = data_per_group_30,
aes(
ymin = mean_deviation - ci_deviation,
ymax = mean_deviation + ci_deviation,
fill = prior_anim
),
colour = NA, alpha = 0.3
) + geom_line(
data = data_per_group_30,
aes(
colour = prior_anim
)
)
# set colour palette
p <- p +
scale_colour_manual(values = pallete_list) +
scale_fill_manual(values = pallete_list)
ggplotly(p)
LS0tDQp0aXRsZTogIkJpbGxpYXJkcyBhbmQgVGlsdHMgQW5hbHlzaXMgTm90ZWJvb2siDQphdXRob3I6ICJTaGFuYWF0aGFuYW4gTW9kY2hhbGluZ2FtIg0Kb3V0cHV0OiANCiAgaHRtbF9ub3RlYm9vazoNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCiAgICBkZl9wcmludDogcGFnZWQNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCnJtKGxpc3QgPSBscygpKSAjIGNsZWFuIGVudmlyb25tZW50DQoNCnNvdXJjZSgiLi4vc3JjL2hlbHBlcl9mdW5jcy5SIikNCnNvdXJjZSgiLi4vc2NyaXB0cy9maWd1cmVfZnVuY3MuUiIpDQpsaWJyYXJ5KGRhdGEudGFibGUpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoZ2diZWVzd2FybSkNCmxpYnJhcnkoZXopICMgZm9yIEFOT1ZBcw0KbGlicmFyeShlZmZlY3RzaXplKSAjIGZvciBldGEtc3F1YXJlZA0KbGlicmFyeShwbG90bHkpDQoNCmxpYnJhcnkoZnVycnIpDQpwbGFuKG11bHRpc2Vzc2lvbikNCg0Kb3B0aW9ucyhkcGx5ci5zdW1tYXJpc2UuaW5mb3JtID0gRikNCg0KIyB2YXJzDQpvbW5pYnVzX3BhdGggPC0gIi4uL2RhdGEvcHJvY2Vzc2VkL29tbmlidXMvb21uaWJ1c19yYXcuY3N2Ig0KDQojIGNvbnZlcnQgdGhlIGFib3ZlIGludG8gYSBsaXN0DQpwYWxsZXRlX2xpc3QgPC0gYygNCiAgInJvdDMwX2N1ZWRfdGlsdCIgPSAiI2Q0MDAwMCIsDQogICJyb3QzMF91bmN1ZWQiID0gIiNmOTk4MmMiLA0KICAiYWNjZWxfY3VlZF90aWx0IiA9ICIjMDc1MDliIiwNCiAgImFjY2VsX3VuY3VlZCIgPSAiIzVmYjY5NiIsDQogICJjdXJ2ZWRfY3VlZF90aWx0IiA9ICIjMmI1NzQ3IiwNCiAgInJvdDE1X2N1ZWRfdGlsdCIgPSAiIzc3MDIwMiIsDQogICJyb3QxNV91bmN1ZWQiID0gIiNhNzYzMTUiLA0KICAibm9uZSIgPSAiI2Y5OTgyYyIsDQogICJoYWxmX2FuaW0iID0gIiM1ZmI2OTYiLA0KICAiZnVsbF9hbmltIiA9ICIjMDc1MDliIiwNCiAgIndhaXQiID0gIiNhNzYzMTUiDQopDQoNCk5VTV9FWFBTIDwtIDcNCmBgYA0KDQoNCg0KIyMgTG9hZCBhbGwgb2YgdGhlIHRocm93IGRhdGENCg0KDQoNCmBgYHtyfQ0KIyBsb2FkIG9tbmlidXMgZGF0YWZyYW1lDQpvbW5pYnVzX2RmIDwtIHJlYWRfZGVsaW0oIi4uL2RhdGEvcHJvY2Vzc2VkL29tbmlidXMvb21uaWJ1c19yYXcuY3N2IiwNCiAgZGVsaW0gPSAiLCIsDQogIGNvbF90eXBlcyA9IGNvbHMoDQogICAgLmRlZmF1bHQgPSBjb2xfZG91YmxlKCksDQogICAgdHlwZSA9IGNvbF9mYWN0b3IoKSwNCiAgICBwcGlkID0gY29sX2ZhY3RvcigpLA0KICAgIGV4cF9sYWJlbCA9IGNvbF9mYWN0b3IoKSwNCiAgICBleHBlcmltZW50ID0gY29sX2ZhY3RvcigpLA0KICAgIGhhbmQgPSBjb2xfZmFjdG9yKCksDQogICAgY2FtZXJhX3RpbHQgPSBjb2xfZmFjdG9yKCksDQogICAgc3VyZmFjZV90aWx0ID0gY29sX2ZhY3RvcigpLA0KICAgIHRhcmdldCA9IGNvbF9mYWN0b3IoKSwNCiAgICB0ZXN0X3R5cGUgPSBjb2xfZmFjdG9yKCksDQogICAgcHJpb3JfYW5pbSA9IGNvbF9mYWN0b3IoKSwNCiAgICBiYXNlbGluZV9ibG9jayA9IGNvbF9mYWN0b3IoKSwNCiAgICB0YXNrX3R5cGUgPSBjb2xfZmFjdG9yKCksDQogICAgc3VyZmFjZSA9IGNvbF9mYWN0b3IoKSwNCiAgICBhbmltX3R5cGUgPSBjb2xfZmFjdG9yKCkNCiAgKQ0KKSAlPiUgIyBmaWx0ZXIgb3V0IHByYWN0aWNlIGJsb2Nrcw0KICBmaWx0ZXIoYmxvY2tfbnVtID4gNCkNCg0KIyBPcHRpb25hbGx5IG1ha2UgbGVhcm5pbmcgcmF0ZSBzdW1tYXJpZXMNCiMgZG8gdGhlIGZvbGxvd2luZyBpZiBsZWFybmluZ19yYXRlX2RmLmNzdiBkb2Vzbid0IGV4aXN0IGluIC4uL2RhdGEvcHJvY2Vzc2VkDQojIFRoaXMgdGFrZXMgYSBsb29uZyB0aW1lDQppZiAoIWZpbGUuZXhpc3RzKCIuLi9kYXRhL3Byb2Nlc3NlZC9sZWFybmluZ19yYXRlX2RmLmNzdiIpKSB7DQogIHByaW50KFN5cy50aW1lKCkpDQogIGFwcGx5X2V4cG9uZW50aWFsRml0IDwtIGZ1bmN0aW9uKGRmKSB7DQogICAgZGYgJT4lDQogICAgICBzdW1tYXJpc2UoDQogICAgICAgIHBwaWQgPSBmaXJzdChwcGlkKSwNCiAgICAgICAgZXhwZXJpbWVudCA9IGZpcnN0KGV4cGVyaW1lbnQpLA0KICAgICAgICB0ZXN0X3R5cGUgPSBmaXJzdCh0ZXN0X3R5cGUpLA0KICAgICAgICBleHBvbmVudGlhbEZpdCA9IGV4cG9uZW50aWFsRml0Mihub3JtX3Rocm93X2RldmlhdGlvbiwgbW9kZSA9IHRlc3RfdHlwZVsxXSkNCiAgICAgICkNCiAgfQ0KDQogIGJsb2NrX2luaXRfbGVhcm5pbmdfcmF0ZXMgPC0gb21uaWJ1c19kZiAlPiUNCiAgICBmaWx0ZXIoc3RyX2RldGVjdCh0ZXN0X3R5cGUsICJpbml0IikpICU+JQ0KICAgIGdyb3VwX2J5KHBwaWQsIGV4cGVyaW1lbnQsIHRlc3RfdHlwZSkgJT4lDQogICAgZ3JvdXBfc3BsaXQoKSAlPiUNCiAgICBmdXR1cmVfbWFwKGFwcGx5X2V4cG9uZW50aWFsRml0KSAlPiUNCiAgICBiaW5kX3Jvd3MoKSAlPiUNCiAgICB1bm5lc3QoY29scyA9IGMoImV4cG9uZW50aWFsRml0IikpDQoNCiAgcHJpbnQoImRvbmUiKQ0KICBwcmludChTeXMudGltZSgpKQ0KDQogIHdyaXRlX2NzdihibG9ja19pbml0X2xlYXJuaW5nX3JhdGVzLCAiLi4vZGF0YS9wcm9jZXNzZWQvbGVhcm5pbmdfcmF0ZV9kZi5jc3YiKQ0KfSBlbHNlIHsNCiAgcHJpbnQoImxlYXJuaW5nX3JhdGVfZGYuY3N2IGV4aXN0cywgbG9hZGluZyBmcm9tIGZpbGUiKQ0KICBibG9ja19pbml0X2xlYXJuaW5nX3JhdGVzIDwtIHJlYWRfY3N2KCIuLi9kYXRhL3Byb2Nlc3NlZC9sZWFybmluZ19yYXRlX2RmLmNzdiIsDQogICAgY29sX3R5cGVzID0gY29scygNCiAgICAgIC5kZWZhdWx0ID0gY29sX2RvdWJsZSgpLA0KICAgICAgZXhwZXJpbWVudCA9IGNvbF9mYWN0b3IoKSwNCiAgICAgIHRlc3RfdHlwZSA9IGNvbF9mYWN0b3IoKQ0KICAgICkNCiAgKQ0KfQ0KYGBgDQoNCiMgVmlzdWFsaXppbmcgZGF0YSAodW5pdmFyaWF0ZSkNClZlY3RvcnMgcmVwcmVzZW50aW5nIHRoZSB0aHJvdyB2ZWxvY2l0eSAodHJhY2UgMCkgYW5kIHRoZSB2ZWxvY2l0eSBhcHBsaWVkIHRvIHRoZSBiYWxsICh0cmFjZSAxKS4gVGhlIHkgZGltZW50aW9uIG9mIHRoZSB0aHJvdyBpcyBlc3NlbnRpYWxseSBpZ25vcmVkIChpbiByZWFsaXR5IHRoZXJlIGlzIGEgc2xpZ2h0IHRpbHQgYWRkZWQgdG8gYWNjb3VudCBmb3IgdGhlIHRpbHQgb2YgdGhlIHN1cmZhY2UpLg0KYGBge3J9DQp0ZXN0X3BwdCA8LSAzDQoNCnRlc3RfZGYgPC0gb21uaWJ1c19kZiAlPiUgZmlsdGVyKHBwaWQgPT0gdGVzdF9wcHQpDQoNCg0KdHJpYWwgPC0gMjUwDQp0cmlhbF9kZiA8LSBmaWx0ZXIodGVzdF9kZiwgdHJpYWxfbnVtID09IHRyaWFsKQ0KDQp4IDwtIHRyaWFsX2RmJGZsaWNrX3ZlbG9jaXR5X3gNCnkgPC0gdHJpYWxfZGYkZmxpY2tfdmVsb2NpdHlfeQ0KeiA8LSB0cmlhbF9kZiRmbGlja192ZWxvY2l0eV96DQoNCngyIDwtIHRyaWFsX2RmJGZsaWNrX2RpcmVjdGlvbl94ICogLTENCnkyIDwtIHRyaWFsX2RmJGZsaWNrX2RpcmVjdGlvbl95ICogLTENCnoyIDwtIHRyaWFsX2RmJGZsaWNrX2RpcmVjdGlvbl96ICogLTENCg0KIyBwbG90IGJvdGgNCnAgPC0gcGxvdF9seSh4ID0gYygwLCB4KSwgeSA9IGMoMCwgeSksIHogPSBjKDAsIHopLCB0eXBlID0gInNjYXR0ZXIzZCIsIG1vZGUgPSAibGluZXMiKSAlPiUNCiAgYWRkX3RyYWNlKHggPSBjKDAsIHgyKSwgeSA9IGMoMCwgeTIpLCB6ID0gYygwLCB6MiksIHR5cGUgPSAic2NhdHRlcjNkIiwgbW9kZSA9ICJsaW5lcyIpICU+JQ0KICBsYXlvdXQoc2NlbmUgPSBsaXN0KA0KICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJ4IiwgcmFuZ2UgPSBjKC0yLCAyKSksDQogICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gInkiLCByYW5nZSA9IGMoLTEsIDMpKSwNCiAgICB6YXhpcyA9IGxpc3QodGl0bGUgPSAieiIsIHJhbmdlID0gYygtMSwgMykpLA0KICAgIGFzcGVjdG1vZGUgPSAiY3ViZSIgIyBlcXVhbCBhc3BlY3QgcmF0aW9zDQogICkpDQoNCiMgUmVuZGVyIHRoZSBwbG90DQpwDQpgYGANCm5vdGU6IHRoaXMgaXMgYSByb3RhdGVkIHRyaWFsDQoNCiMjIyBEaXN0cmlidXRpb24gb2YgZXJyb3JzDQpgYGB7cn0NCiMgcGxvdCBkaXN0cmlidXRpb24gb2YgZXJyb3Jfc2l6ZQ0KcCA8LSBnZ3Bsb3Qob21uaWJ1c19kZiwgYWVzKA0KICB4ID0gZXJyb3Jfc2l6ZSwNCiAgZmlsbCA9IHR5cGUNCikpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAuNSwgYWxwaGEgPSAuNikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSkpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiI2Y5OTgyYyIsICIjZDQwMDAwIikpICsNCiAgbGFicyh4ID0gIkVycm9yIFNpemUgKGNtKSIsIHkgPSAiQ291bnQiKQ0KDQpwDQpgYGANCg0KIyMjIERpc3RyaWJ1dGlvbiBvZiB0aHJvdyBhbmdsZXMNCmBgYHtyfQ0KIyBwbG90IGRpc3RyaWJ1dGlvbiBvZiBlcnJvcl9zaXplDQpwIDwtIGdncGxvdChvbW5pYnVzX2RmLCBhZXMoDQogIHggPSB0aHJvd19kZXZpYXRpb24sDQogIGZpbGwgPSB0eXBlDQopKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgYWxwaGEgPSAuNikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSkpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiI2Y5OTgyYyIsICIjZDQwMDAwIikpICsNCiAgbGFicygNCiAgICB4ID0gIlRocm93IEFuZ2xlICjCsCkiLCB5ID0gIkNvdW50Ig0KICApICsgIyBkYXNoZWQgbGluZXMgYXQgMCwgLTE1LCAtMzANCiAgZ2VvbV92bGluZSgNCiAgICB4aW50ZXJjZXB0ID0gYygwLCAtMTUsIC0zMCksIGxpbmV3aWR0aCA9IDAuNCwNCiAgICBjb2xvdXIgPSAiI0NDQ0NDQyIsIGxpbmV0eXBlID0gImRhc2hlZCINCiAgKSArICMgdGlja3Mgb2YgMTUgZGVncmVlcw0KICBzY2FsZV94X2NvbnRpbnVvdXMoDQogICAgYnJlYWtzID0gYygtMzAsIDAsIDMwLCAtNjAsIC05MCkNCiAgKQ0KDQpwDQpgYGANCg0KIyBPcmlnaW5hbCBFeHBlcmltZW50cw0KDQojIyMgUGxvdCBBTkdVTEFSIERFVklBVElPTlMgKGhhbmQgYW5nbGVzKQ0KTm90ZTogQmx1ZXMgPSBBY2NlbGVyYXRpb24gUGVydHVyYmF0aW9ucw0KYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02LCBvdXQud2lkdGg9IjEwMCUifQ0KIyByZXN0IG9mIHRoZSBleHBzDQpkYXRhX3Blcl9ncm91cCA8LSBvbW5pYnVzX2RmICU+JQ0KICBmaWx0ZXIoZXhwX2xhYmVsID09ICJvcmlnaW5hbF9leHBzIiB8IGV4cF9sYWJlbCA9PSAiY3VydmVkX3BhdGgiKSAlPiUNCiAgZ3JvdXBfYnkoZXhwZXJpbWVudCwgdGVzdF90eXBlLCB0cmlhbF9udW0pICU+JQ0KICBzdW1tYXJpc2UoDQogICAgbWVhbl9kZXZpYXRpb24gPSBtZWFuKHRocm93X2RldmlhdGlvbiksDQogICAgY2lfZGV2aWF0aW9uID0gdmVjdG9yX2NvbmZpbnQodGhyb3dfZGV2aWF0aW9uKSwNCiAgICAuZ3JvdXBzID0gImRyb3AiDQogICkNCg0KIyBzZXQgdXAgcGxvdA0KcCA8LSBkYXRhX3Blcl9ncm91cCAlPiUNCiAgZ2dwbG90KA0KICAgIGFlcygNCiAgICAgIHggPSB0cmlhbF9udW0sIHkgPSBtZWFuX2RldmlhdGlvbiwgY29sb3VyID0gZXhwZXJpbWVudA0KICAgICkNCiAgKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogICMgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArDQogIGxhYnMoDQogICAgeCA9ICJUcmlhbCBOdW1iZXIiLA0KICAgIHkgPSAiVGhyb3cgQW5nbGUgKMKwKSINCiAgKQ0KDQojIGFkZCBob3Jpem9udGFsIGxpbmVzDQpwIDwtIHAgKw0KICBnZW9tX2hsaW5lKA0KICAgIHlpbnRlcmNlcHQgPSBjKDAsIC0zMCksIGxpbmV3aWR0aCA9IDAuNCwNCiAgICBjb2xvdXIgPSAiI0NDQ0NDQyIsIGxpbmV0eXBlID0gInNvbGlkIg0KICApICsNCiAgZ2VvbV9obGluZSgNCiAgICB5aW50ZXJjZXB0ID0gYygtMTUpLCBsaW5ld2lkdGggPSAwLjQsDQogICAgY29sb3VyID0gIiNDQ0NDQ0MiLCBsaW5ldHlwZSA9ICJkYXNoZWQiDQogICkNCg0KIyBwIDwtIHAgKw0KIyAgIHNjYWxlX3lfY29udGludW91cygNCiMgICAgIGxpbWl0cyA9IGMoLTEwLCAzNSksDQojICAgICBicmVha3MgPSBjKDAsIDE1LCAzMCksDQojICAgICBsYWJlbHMgPSBjKDAsIDE1LCAzMCkNCiMgICApICsNCiMgICBzY2FsZV94X2NvbnRpbnVvdXMoDQojICAgICBsaW1pdHMgPSBjKDAsIDE4MCksDQojICAgICBicmVha3MgPSBjKDAsIDYwLCAxMjAsIDE4MCksDQojICAgICBsYWJlbHMgPSBjKDAsIDYwLCAxMjAsIDE4MCkNCiMgICApDQoNCiMgc2V0IGZvbnQgc2l6ZSB0byAxMQ0KcCA8LSBwICsNCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKQ0KDQojIGFkZCBjb25maWRlbmNlIGludGVydmFscyBhbmQgZGF0YSBwb2ludHMNCnAgPC0gcCArIGdlb21fcmliYm9uKA0KICBhZXMoDQogICAgeW1pbiA9IG1lYW5fZGV2aWF0aW9uIC0gY2lfZGV2aWF0aW9uLA0KICAgIHltYXggPSBtZWFuX2RldmlhdGlvbiArIGNpX2RldmlhdGlvbiwNCiAgICBmaWxsID0gZXhwZXJpbWVudA0KICApLA0KICBjb2xvdXIgPSBOQSwgYWxwaGEgPSAwLjMNCikgKyBnZW9tX2xpbmUoKQ0KDQojIHNldCBjb2xvdXIgcGFsZXR0ZQ0KcCA8LSBwICsNCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBwYWxsZXRlX2xpc3QpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsbGV0ZV9saXN0KQ0KDQoNCiMgIyBzYXZlDQojIGlmIChzYXZlX3Bsb3RzKSB7DQojICAgZ2dzYXZlKA0KIyAgIHAsDQojICAgZmlsZW5hbWUgPSAiLi4vcGxvdHMvcGFwZXJfZmlncy9zcl8zMF90cmFpbmluZy5wZGYiLCBkZXZpY2UgPSAicGRmIiwNCiMgICBoZWlnaHQgPSA0LCB3aWR0aCA9IDYNCiMgICApDQojICAgfQ0KDQpnZ3Bsb3RseShwKQ0KDQojIHANCmBgYA0KIyMjIFRyaWFsIHNldHMgb2YgaW50ZXJlc3Qgb25seQ0KTm90ZTogQmx1ZXMgPSBBY2NlbGVyYXRpb24gUGVydHVyYmF0aW9ucw0KYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02LCBvdXQud2lkdGg9IjEwMCUifQ0KIyBmaWx0ZXIgb3V0IGp1c3QgdGhlIHRyaWFscyBvZiBpbnRlcmVzdA0KZGF0YV9wZXJfZ3JvdXAgPC0gZGF0YV9wZXJfZ3JvdXAgJT4lDQogIGZpbHRlcigNCiAgICB0ZXN0X3R5cGUgIT0gIm90aGVyIg0KICApDQojIGFkZCBhIGR1bW15IGNvbHVtbiB3aXRoIHJlcGVhdGluZyBzZXF1ZW5jZQ0KIyBOT1RFOiB0aGlzIGNhbid0IGJlIGNvbWJpbmVkIHdpdGggYWJvdmUgc2luY2Ugd2UgYXJlIHVzaW5nIG5yb3cNCmRhdGFfcGVyX2dyb3VwIDwtIGRhdGFfcGVyX2dyb3VwICU+JQ0KICBtdXRhdGUoZHVtbXlfeCA9IHJlcCgxOihucm93KGRhdGFfcGVyX2dyb3VwKSAvIE5VTV9FWFBTKSwNCiAgICBsZW5ndGgub3V0ID0gbnJvdyhkYXRhX3Blcl9ncm91cCkNCiAgKSkNCg0KIyBzZXQgdXAgcGxvdA0KcCA8LSBkYXRhX3Blcl9ncm91cCAlPiUNCiAgZ2dwbG90KA0KICAgIGFlcygNCiAgICAgIHggPSBkdW1teV94LCB5ID0gbWVhbl9kZXZpYXRpb24sIGNvbG91ciA9IGV4cGVyaW1lbnQNCiAgICApDQogICkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICAjIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKw0KICBsYWJzKA0KICAgIHggPSAiVHJpYWwgTnVtYmVyIiwNCiAgICB5ID0gIlRocm93IEFuZ2xlICjCsCkiDQogICkNCg0KIyBhZGQgaG9yaXpvbnRhbCBsaW5lcw0KcCA8LSBwICsNCiAgZ2VvbV9obGluZSgNCiAgICB5aW50ZXJjZXB0ID0gYygwLCAtMzApLCBsaW5ld2lkdGggPSAwLjQsDQogICAgY29sb3VyID0gIiNDQ0NDQ0MiLCBsaW5ldHlwZSA9ICJzb2xpZCINCiAgKSArDQogIGdlb21faGxpbmUoDQogICAgeWludGVyY2VwdCA9IGMoLTE1KSwgbGluZXdpZHRoID0gMC40LA0KICAgIGNvbG91ciA9ICIjQ0NDQ0NDIiwgbGluZXR5cGUgPSAiZGFzaGVkIg0KICApDQoNCiMgYWRkIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGFuZCBkYXRhIHBvaW50cw0KZm9yICh1bmlxdWVfdGVzdF90eXBlIGluIHVuaXF1ZShkYXRhX3Blcl9ncm91cCR0ZXN0X3R5cGUpKSB7DQogICMgZ2V0IHRoZSBkYXRhIGZvciB0aGlzIGJsb2NrDQogIHRvX3Bsb3RfZGF0YSA8LSBmaWx0ZXIoZGF0YV9wZXJfZ3JvdXAsIHRlc3RfdHlwZSA9PSB1bmlxdWVfdGVzdF90eXBlKQ0KDQogIHAgPC0gcCArIGdlb21fcmliYm9uKA0KICAgIGRhdGEgPSB0b19wbG90X2RhdGEsDQogICAgYWVzKA0KICAgICAgeW1pbiA9IG1lYW5fZGV2aWF0aW9uIC0gY2lfZGV2aWF0aW9uLA0KICAgICAgeW1heCA9IG1lYW5fZGV2aWF0aW9uICsgY2lfZGV2aWF0aW9uLA0KICAgICAgZmlsbCA9IGV4cGVyaW1lbnQNCiAgICApLCBjb2xvdXIgPSBOQSwgYWxwaGEgPSAwLjMNCiAgKSArIGdlb21fbGluZSgNCiAgICBkYXRhID0gdG9fcGxvdF9kYXRhDQogICkNCn0NCg0KIyBzZXQgY29sb3VyIHBhbGV0dGUNCnAgPC0gcCArDQogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gcGFsbGV0ZV9saXN0KSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHBhbGxldGVfbGlzdCkNCg0KZ2dwbG90bHkocCkNCmBgYA0KIyMjIFBsb3QgTk9STUFMSVpFRCBBTkdVTEFSIERFVklBVElPTlMgKGhhbmQgYW5nbGVzKQ0KTm90ZTogQmx1ZXMgPSBBY2NlbGVyYXRpb24gUGVydHVyYmF0aW9ucw0KYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02LCBvdXQud2lkdGg9IjEwMCUifQ0KIyByZXN0IG9mIHRoZSBleHBzDQpkYXRhX3Blcl9ncm91cCA8LSBvbW5pYnVzX2RmICU+JQ0KICBmaWx0ZXIoZXhwX2xhYmVsID09ICJvcmlnaW5hbF9leHBzIiB8IGV4cF9sYWJlbCA9PSAiY3VydmVkX3BhdGgiKSAlPiUNCiAgZ3JvdXBfYnkoZXhwZXJpbWVudCwgdGVzdF90eXBlLCB0cmlhbF9udW0pICU+JQ0KICBzdW1tYXJpc2UoDQogICAgbWVhbl9kZXZpYXRpb24gPSBtZWFuKG5vcm1fdGhyb3dfZGV2aWF0aW9uKSwNCiAgICBjaV9kZXZpYXRpb24gPSB2ZWN0b3JfY29uZmludChub3JtX3Rocm93X2RldmlhdGlvbiksDQogICAgLmdyb3VwcyA9ICJkcm9wIg0KICApDQoNCiMgc2V0IHVwIHBsb3QNCnAgPC0gZGF0YV9wZXJfZ3JvdXAgJT4lDQogIGdncGxvdCgNCiAgICBhZXMoDQogICAgICB4ID0gdHJpYWxfbnVtLCB5ID0gbWVhbl9kZXZpYXRpb24sIGNvbG91ciA9IGV4cGVyaW1lbnQNCiAgICApDQogICkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICAjIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKw0KICBsYWJzKA0KICAgIHggPSAiVHJpYWwgTnVtYmVyIiwNCiAgICB5ID0gIk5vcm1hbGl6ZWQgVGhyb3cgQW5nbGUiDQogICkNCg0KIyBhZGQgaG9yaXpvbnRhbCBsaW5lcw0KcCA8LSBwICsNCiAgZ2VvbV9obGluZSgNCiAgICB5aW50ZXJjZXB0ID0gYygwLCAxLCAyKSwgbGluZXdpZHRoID0gMC40LA0KICAgIGNvbG91ciA9ICIjQ0NDQ0NDIiwgbGluZXR5cGUgPSAic29saWQiDQogICkgKw0KICBnZW9tX2hsaW5lKA0KICAgIHlpbnRlcmNlcHQgPSBjKDAuNSwgMS41KSwgbGluZXdpZHRoID0gMC40LA0KICAgIGNvbG91ciA9ICIjQ0NDQ0NDIiwgbGluZXR5cGUgPSAiZGFzaGVkIg0KICApDQoNCiMgcCA8LSBwICsNCiMgICBzY2FsZV95X2NvbnRpbnVvdXMoDQojICAgICBsaW1pdHMgPSBjKC0xMCwgMzUpLA0KIyAgICAgYnJlYWtzID0gYygwLCAxNSwgMzApLA0KIyAgICAgbGFiZWxzID0gYygwLCAxNSwgMzApDQojICAgKSArDQojICAgc2NhbGVfeF9jb250aW51b3VzKA0KIyAgICAgbGltaXRzID0gYygwLCAxODApLA0KIyAgICAgYnJlYWtzID0gYygwLCA2MCwgMTIwLCAxODApLA0KIyAgICAgbGFiZWxzID0gYygwLCA2MCwgMTIwLCAxODApDQojICAgKQ0KDQojIHNldCBmb250IHNpemUgdG8gMTENCnAgPC0gcCArDQogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSkNCg0KIyBhZGQgY29uZmlkZW5jZSBpbnRlcnZhbHMgYW5kIGRhdGEgcG9pbnRzDQpwIDwtIHAgKyBnZW9tX3JpYmJvbigNCiAgYWVzKA0KICAgIHltaW4gPSBtZWFuX2RldmlhdGlvbiAtIGNpX2RldmlhdGlvbiwNCiAgICB5bWF4ID0gbWVhbl9kZXZpYXRpb24gKyBjaV9kZXZpYXRpb24sDQogICAgZmlsbCA9IGV4cGVyaW1lbnQNCiAgKSwNCiAgY29sb3VyID0gTkEsIGFscGhhID0gMC4zDQopICsgZ2VvbV9saW5lKCkNCg0KIyBzZXQgY29sb3VyIHBhbGV0dGUNCnAgPC0gcCArDQogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gcGFsbGV0ZV9saXN0KSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHBhbGxldGVfbGlzdCkNCg0KDQojICMgc2F2ZQ0KIyBpZiAoc2F2ZV9wbG90cykgew0KIyAgIGdnc2F2ZSgNCiMgICBwLA0KIyAgIGZpbGVuYW1lID0gIi4uL3Bsb3RzL3BhcGVyX2ZpZ3Mvc3JfMzBfdHJhaW5pbmcucGRmIiwgZGV2aWNlID0gInBkZiIsDQojICAgaGVpZ2h0ID0gNCwgd2lkdGggPSA2DQojICAgKQ0KIyAgIH0NCg0KZ2dwbG90bHkocCkNCg0KIyBwDQpgYGANCiMjIyBUcmlhbCBzZXRzIG9mIGludGVyZXN0IG9ubHkNCk5vdGU6IEJsdWVzID0gQWNjZWxlcmF0aW9uIFBlcnR1cmJhdGlvbnMNCmBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9Niwgb3V0LndpZHRoPSIxMDAlIn0NCiMgZmlsdGVyIG91dCBqdXN0IHRoZSB0cmlhbHMgb2YgaW50ZXJlc3QNCmRhdGFfcGVyX2dyb3VwIDwtIGRhdGFfcGVyX2dyb3VwICU+JQ0KICBmaWx0ZXIoDQogICAgdGVzdF90eXBlICE9ICJvdGhlciINCiAgKQ0KIyBhZGQgYSBkdW1teSBjb2x1bW4gd2l0aCByZXBlYXRpbmcgc2VxdWVuY2UNCiMgTk9URTogdGhpcyBjYW4ndCBiZSBjb21iaW5lZCB3aXRoIGFib3ZlIHNpbmNlIHdlIGFyZSB1c2luZyBucm93DQpkYXRhX3Blcl9ncm91cCA8LSBkYXRhX3Blcl9ncm91cCAlPiUNCiAgbXV0YXRlKGR1bW15X3ggPSByZXAoMToobnJvdyhkYXRhX3Blcl9ncm91cCkgLyBOVU1fRVhQUyksDQogICAgbGVuZ3RoLm91dCA9IG5yb3coZGF0YV9wZXJfZ3JvdXApDQogICkpDQoNCiMgc2V0IHVwIHBsb3QNCnAgPC0gZGF0YV9wZXJfZ3JvdXAgJT4lDQogIGdncGxvdCgNCiAgICBhZXMoDQogICAgICB4ID0gZHVtbXlfeCwgeSA9IG1lYW5fZGV2aWF0aW9uLCBjb2xvdXIgPSBleHBlcmltZW50DQogICAgKQ0KICApICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgIyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsNCiAgbGFicygNCiAgICB4ID0gIlRyaWFsIE51bWJlciIsDQogICAgeSA9ICJOb3JtYWxpemVkIFRocm93IEFuZ2xlIg0KICApDQoNCiMgYWRkIGhvcml6b250YWwgbGluZXMNCnAgPC0gcCArDQogIGdlb21faGxpbmUoDQogICAgeWludGVyY2VwdCA9IGMoMCwgMSwgMiksIGxpbmV3aWR0aCA9IDAuNCwNCiAgICBjb2xvdXIgPSAiI0NDQ0NDQyIsIGxpbmV0eXBlID0gInNvbGlkIg0KICApICsNCiAgZ2VvbV9obGluZSgNCiAgICB5aW50ZXJjZXB0ID0gYygwLjUsIDEuNSksIGxpbmV3aWR0aCA9IDAuNCwNCiAgICBjb2xvdXIgPSAiI0NDQ0NDQyIsIGxpbmV0eXBlID0gImRhc2hlZCINCiAgKQ0KDQojIGFkZCBjb25maWRlbmNlIGludGVydmFscyBhbmQgZGF0YSBwb2ludHMNCmZvciAodW5pcXVlX3Rlc3RfdHlwZSBpbiB1bmlxdWUoZGF0YV9wZXJfZ3JvdXAkdGVzdF90eXBlKSkgew0KICAjIGdldCB0aGUgZGF0YSBmb3IgdGhpcyBibG9jaw0KICB0b19wbG90X2RhdGEgPC0gZmlsdGVyKGRhdGFfcGVyX2dyb3VwLCB0ZXN0X3R5cGUgPT0gdW5pcXVlX3Rlc3RfdHlwZSkNCg0KICBwIDwtIHAgKyBnZW9tX3JpYmJvbigNCiAgICBkYXRhID0gdG9fcGxvdF9kYXRhLA0KICAgIGFlcygNCiAgICAgIHltaW4gPSBtZWFuX2RldmlhdGlvbiAtIGNpX2RldmlhdGlvbiwNCiAgICAgIHltYXggPSBtZWFuX2RldmlhdGlvbiArIGNpX2RldmlhdGlvbiwNCiAgICAgIGZpbGwgPSBleHBlcmltZW50DQogICAgKSwgY29sb3VyID0gTkEsIGFscGhhID0gMC4zDQogICkgKyBnZW9tX2xpbmUoDQogICAgZGF0YSA9IHRvX3Bsb3RfZGF0YQ0KICApDQp9DQoNCiMgc2V0IGNvbG91ciBwYWxldHRlDQpwIDwtIHAgKw0KICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHBhbGxldGVfbGlzdCkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxsZXRlX2xpc3QpDQoNCmdncGxvdGx5KHApDQpgYGANCg0KIyMgTGVhcm5pbmcgUmF0ZXMsIFN0YXJ0IFBvaW50cyBhbmQgQXN5bXB0b3Rlcw0KIyMjIExlYXJuaW5nIFJhdGVzDQpgYGB7ciwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTYsIG91dC53aWR0aD0iMTAwJSJ9DQpkYXRhX3BwdCA8LSBibG9ja19pbml0X2xlYXJuaW5nX3JhdGVzICU+JQ0KICBmaWx0ZXIoZXhwZXJpbWVudCAhPSAiYV9iYWxsX3JvbGxfYW5pbWF0ZV9zdXJmYWNlIikNCg0KZGF0YV9ncm91cCA8LSBkYXRhX3BwdCAlPiUNCiAgZ3JvdXBfYnkoZXhwZXJpbWVudCwgdGVzdF90eXBlKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIG1lYW5fbGVhcm5pbmdfcmF0ZSA9IG1lYW4oZXhwX2ZpdF9sYW1iZGEpLA0KICAgIGNpX2xlYXJuaW5nX3JhdGUgPSB2ZWN0b3JfY29uZmludChleHBfZml0X2xhbWJkYSksDQogICAgbWVhbl9oaWdoID0gbWVhbihleHBfZml0X04wKSwNCiAgICBjaV9oaWdoID0gdmVjdG9yX2NvbmZpbnQoZXhwX2ZpdF9OMCksDQogICAgbWVhbl9sb3cgPSBtZWFuKGV4cF9maXRfZGlzcGxhY2UpLA0KICAgIGNpX2xvdyA9IHZlY3Rvcl9jb25maW50KGV4cF9maXRfZGlzcGxhY2UpLA0KICAgIC5ncm91cHMgPSAiZHJvcCINCiAgKQ0KDQpwIDwtIGRhdGFfZ3JvdXAgJT4lDQogIGdncGxvdCgNCiAgICBhZXMoeCA9IGV4cGVyaW1lbnQsIHkgPSBtZWFuX2xlYXJuaW5nX3JhdGUsIGNvbG91ciA9IGV4cGVyaW1lbnQpDQogICkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICBsYWJzKA0KICAgIHggPSBOVUxMLA0KICAgIHkgPSAiTGVhcm5pbmcgUmF0ZSINCiAgKSArDQogIGZhY2V0X3dyYXAofnRlc3RfdHlwZSkNCg0KIyByZW1vdmUgYWxsIHggYXhpcyBsYWJlbHMNCnAgPC0gcCArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpKQ0KDQojIGZvciB0aGUgY29sb3VyIGxlZ2VuZCwgb25seSBzaG93IHRoZSBmaXJzdCA3IE5vdGUgdGhpcyBkb2Vzbid0IHdvcmsgZm9yIHRoZSBwbG90bHkgcGxvdA0KcCA8LSBwICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KGFscGhhID0gMSkpKQ0KDQojIGFkZCBkYXRhIHBvaW50cw0KcCA8LSBwICsNCiAgZ2VvbV9iZWVzd2FybSgNCiAgICBkYXRhID0gZGF0YV9wcHQsDQogICAgYWVzKA0KICAgICAgeSA9IGV4cF9maXRfbGFtYmRhDQogICAgKSwNCiAgICBhbHBoYSA9IDAuMSwNCiAgICBzaXplID0gMQ0KICApICsNCiAgZ2VvbV9saW5lcmFuZ2UoYWVzKA0KICAgIHltaW4gPSBtZWFuX2xlYXJuaW5nX3JhdGUgLSBjaV9sZWFybmluZ19yYXRlLA0KICAgIHltYXggPSBtZWFuX2xlYXJuaW5nX3JhdGUgKyBjaV9sZWFybmluZ19yYXRlDQogICksIGFscGhhID0gMC41LCBsd2QgPSAyKSArDQogIGdlb21fcG9pbnQoKQ0KDQojIHNldCBjb2xvdXIgcGFsZXR0ZQ0KcCA8LSBwICsNCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBwYWxsZXRlX2xpc3QpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsbGV0ZV9saXN0KQ0KDQpnZ3Bsb3RseShwKQ0KIyBwDQpgYGANCg0KIyMjIEhpZ2ggUG9pbnRzIChBc3ltcHRvdGVzIG9yIFN0YXJ0cykNCmBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9Niwgb3V0LndpZHRoPSIxMDAlIn0NCnAgPC0gZGF0YV9ncm91cCAlPiUNCiAgZ2dwbG90KA0KICAgIGFlcyh4ID0gZXhwZXJpbWVudCwgeSA9IG1lYW5faGlnaCwgY29sb3VyID0gZXhwZXJpbWVudCkNCiAgKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogIGxhYnMoDQogICAgeCA9IE5VTEwsDQogICAgeSA9ICJIaWdoIFBvaW50Ig0KICApICsNCiAgZmFjZXRfd3JhcCh+dGVzdF90eXBlKQ0KDQojIHJlbW92ZSBhbGwgeCBheGlzIGxhYmVscw0KcCA8LSBwICsgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCkpDQoNCiMgZm9yIHRoZSBjb2xvdXIgbGVnZW5kLCBvbmx5IHNob3cgdGhlIGZpcnN0IDcgTm90ZSB0aGlzIGRvZXNuJ3Qgd29yayBmb3IgdGhlIHBsb3RseSBwbG90DQpwIDwtIHAgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3QoYWxwaGEgPSAxKSkpDQoNCiMgYWRkIGRhdGEgcG9pbnRzDQpwIDwtIHAgKw0KICBnZW9tX2JlZXN3YXJtKA0KICAgIGRhdGEgPSBkYXRhX3BwdCwNCiAgICBhZXMoDQogICAgICB5ID0gZXhwX2ZpdF9OMA0KICAgICksDQogICAgYWxwaGEgPSAwLjEsDQogICAgc2l6ZSA9IDENCiAgKSArDQogIGdlb21fbGluZXJhbmdlKGFlcygNCiAgICB5bWluID0gbWVhbl9oaWdoIC0gY2lfaGlnaCwNCiAgICB5bWF4ID0gbWVhbl9oaWdoICsgY2lfaGlnaA0KICApLCBhbHBoYSA9IDAuNSwgbHdkID0gMikgKw0KICBnZW9tX3BvaW50KCkNCg0KIyBzZXQgY29sb3VyIHBhbGV0dGUNCnAgPC0gcCArDQogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gcGFsbGV0ZV9saXN0KSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHBhbGxldGVfbGlzdCkNCg0KZ2dwbG90bHkocCkNCiMgcA0KYGBgDQojIyMgTG93IFBvaW50cyAoQXN5bXB0b3RlcyBvciBTdGFydHMpDQpgYGB7ciwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTYsIG91dC53aWR0aD0iMTAwJSJ9DQpwIDwtIGRhdGFfZ3JvdXAgJT4lDQogIGdncGxvdCgNCiAgICBhZXMoeCA9IGV4cGVyaW1lbnQsIHkgPSBtZWFuX2xvdywgY29sb3VyID0gZXhwZXJpbWVudCkNCiAgKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogIGxhYnMoDQogICAgeCA9IE5VTEwsDQogICAgeSA9ICJMb3cgUG9pbnQiDQogICkgKw0KICBmYWNldF93cmFwKH50ZXN0X3R5cGUpDQoNCiMgcmVtb3ZlIGFsbCB4IGF4aXMgbGFiZWxzDQpwIDwtIHAgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSkNCg0KIyBmb3IgdGhlIGNvbG91ciBsZWdlbmQsIG9ubHkgc2hvdyB0aGUgZmlyc3QgNyBOb3RlIHRoaXMgZG9lc24ndCB3b3JrIGZvciB0aGUgcGxvdGx5IHBsb3QNCnAgPC0gcCArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChhbHBoYSA9IDEpKSkNCg0KIyBhZGQgZGF0YSBwb2ludHMNCnAgPC0gcCArDQogIGdlb21fYmVlc3dhcm0oDQogICAgZGF0YSA9IGRhdGFfcHB0LA0KICAgIGFlcygNCiAgICAgIHkgPSBleHBfZml0X2Rpc3BsYWNlDQogICAgKSwNCiAgICBhbHBoYSA9IDAuMSwNCiAgICBzaXplID0gMQ0KICApICsNCiAgZ2VvbV9saW5lcmFuZ2UoYWVzKA0KICAgIHltaW4gPSBtZWFuX2xvdyAtIGNpX2xvdywNCiAgICB5bWF4ID0gbWVhbl9sb3cgKyBjaV9sb3cNCiAgKSwgYWxwaGEgPSAwLjUsIGx3ZCA9IDIpICsNCiAgZ2VvbV9wb2ludCgpDQoNCiMgc2V0IGNvbG91ciBwYWxldHRlDQpwIDwtIHAgKw0KICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHBhbGxldGVfbGlzdCkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxsZXRlX2xpc3QpDQoNCmdncGxvdGx5KHApDQojIHANCmBgYA0KDQpGb3Igd2FzaG91dDogVGhlIENVRUQgYWNjZWwgKyBjdXJ2ZWQgaGF2ZSBhIGxvd2VyIHN0YXJ0aW5nIHBvaW50ICh0aGVyZWZvcmUgLS0gY3VlIHdvcmtzKS4gVk1SIGdyb3VwIGhhcyBzbGlnaHRseSBsb3dlci4NCldoZW4gY29tcGFyaW5nIGV2ZXJ5dGhpbmcgd2l0aCBhIGhpZ2ggc3RhcnRpbmcgcG9pbnQsIHRoZSAgQUNDRUwgZ3JvdXAgaGFzIGEgbXVjaCBGQVNURVIgbGVhcm5pbmcgcmF0ZS4gDQpXaGVuIHRyYW5zZmVycmluZywgbm8gZGlmZmVyZW5jZSBpbiBsZWFybmluZyByYXRlcy4NCg0KYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02LCBvdXQud2lkdGg9IjEwMCUifQ0KIyBDb21wYXJlIGxlYXJuaW5nIHJhdGVzIGFuZCBoaWdoIHBvaW50cw0KcCA8LSBkYXRhX3BwdCAlPiUNCiAgZ2dwbG90KA0KICAgIGFlcyh4ID0gZXhwX2ZpdF9sYW1iZGEsIHkgPSBleHBfZml0X04wLCBjb2xvdXIgPSBleHBlcmltZW50KQ0KICApICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgbGFicygNCiAgICB4ID0gIkxlYXJuaW5nIFJhdGUiLA0KICAgIHkgPSAiSGlnaCBQb2ludCINCiAgKSArDQogIGZhY2V0X3dyYXAofnRlc3RfdHlwZSkgKw0KICBnZW9tX3BvaW50KCkgKw0KICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHBhbGxldGVfbGlzdCkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxsZXRlX2xpc3QpDQoNCmdncGxvdGx5KHApDQpgYGANCg0KIyMjIENvcnJlbGF0aW9ucyB3aXRoaW4gdGhlIDMgdmFyaWFibGVzIGFib3ZlDQoNCmBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9Niwgb3V0LndpZHRoPSIxMDAlIiwgd2FybmluZz1GQUxTRX0NCiMgM2QgcGxvdCBvZiBsZWFybmluZyByYXRlcywgaGlnaCBwb2ludHMsIGFuZCBsb3cgcG9pbnRzDQojIGZpbHRlciBvdXQganVzdCB0aGUgd2FzaG91dCB0cmlhbHMgZm9yIG5vdw0KZGF0YV9wcHQgPC0gYmxvY2tfaW5pdF9sZWFybmluZ19yYXRlcyAlPiUNCiAgZmlsdGVyKHRlc3RfdHlwZSA9PSAid2FzaG91dF9pbml0IikNCg0KcCA8LSBwbG90X2x5KHR5cGUgPSAic2NhdHRlcjNkIiwgbW9kZSA9ICJtYXJrZXJzIikNCg0KZm9yIChleHBlcmltZW50XyBpbiB1bmlxdWUoZGF0YV9wcHQkZXhwZXJpbWVudCkpIHsNCiAgIyBnZXQgdGhlIGRhdGEgZm9yIHRoaXMgYmxvY2sNCiAgdG9fcGxvdF9kYXRhIDwtIGZpbHRlcihkYXRhX3BwdCwgZXhwZXJpbWVudCA9PSBleHBlcmltZW50XykNCg0KICBwIDwtIHAgJT4lDQogICAgYWRkX3RyYWNlKA0KICAgICAgeCA9IHRvX3Bsb3RfZGF0YSRleHBfZml0X2xhbWJkYSwNCiAgICAgIHkgPSB0b19wbG90X2RhdGEkZXhwX2ZpdF9OMCwNCiAgICAgIHogPSB0b19wbG90X2RhdGEkZXhwX2ZpdF9kaXNwbGFjZSwNCiAgICAgIGNvbG9yID0gSShwYWxsZXRlX2xpc3RbZXhwZXJpbWVudF9dKSwNCiAgICAgIG5hbWUgPSBleHBlcmltZW50Xw0KICAgICkNCn0NCg0KIyBBeGVzIG5hbWVzDQpwIDwtIHAgJT4lIGxheW91dCgNCiAgc2NlbmUgPQ0KICAgIChsaXN0KA0KICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIkxlYXJuaW5nIFJhdGUiKSwNCiAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJIaWdoIFBvaW50IiksDQogICAgICB6YXhpcyA9IGxpc3QodGl0bGUgPSAiTG93IFBvaW50IiksDQogICAgICBhc3BlY3Rtb2RlID0gImN1YmUiICMgZXF1YWwgYXNwZWN0IHJhdGlvcw0KICAgICkpDQopDQoNCnANCmBgYA0KDQotIFdlIG1pZ2h0IHdhbnQgdG8gdGVzdCBpZiBkYXRhIHBvaW50cyBjbHVzdGVyIGRpZmZlcmVudGx5IGRlcGVuZGluZyBvbiB0aGUgZXhwZXJpbWVudCBjb25kaXRpb25zLg0KLSBOb3RlOiBJdCBpcyBhIGdvb2QgaWRlYSB0byBkbyBzb21lIEVEQSB0byBjaGVjayBpZiBhbGwgMyBkaW1lbnNpb25zIGFyZSByZXF1aXJlZC4gQ29ycmVsYXRpb24gbWF0cml4Pw0KLSANCg0KYGBge3J9DQojIyMgVEVTVElORw0KIyByZXN0IG9mIHRoZSBleHBzDQpkYXRhXyA8LSBvbW5pYnVzX2RmICU+JQ0KICBmaWx0ZXIoZXhwZXJpbWVudCA9PSAiYWNjZWxfdW5jdWVkIiwgdGVzdF90eXBlID09ICJ3YXNob3V0X2luaXQiKQ0KDQojIHNldCB1cCBwbG90DQpwIDwtIGRhdGFfICU+JQ0KICBnZ3Bsb3QoDQogICAgYWVzKA0KICAgICAgeCA9IHRyaWFsX251bSwgeSA9IG5vcm1fdGhyb3dfZGV2aWF0aW9uLCBjb2xvdXIgPSBwcGlkDQogICAgKQ0KICApICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgIyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsNCiAgbGFicygNCiAgICB4ID0gIlRyaWFsIE51bWJlciIsDQogICAgeSA9ICJOb3JtYWxpemVkIFRocm93IEFuZ2xlIg0KICApDQoNCiMgYWRkIGhvcml6b250YWwgbGluZXMNCnAgPC0gcCArDQogIGdlb21faGxpbmUoDQogICAgeWludGVyY2VwdCA9IGMoMCwgMSwgMiksIGxpbmV3aWR0aCA9IDAuNCwNCiAgICBjb2xvdXIgPSAiI0NDQ0NDQyIsIGxpbmV0eXBlID0gInNvbGlkIg0KICApICsNCiAgZ2VvbV9obGluZSgNCiAgICB5aW50ZXJjZXB0ID0gYygwLjUsIDEuNSksIGxpbmV3aWR0aCA9IDAuNCwNCiAgICBjb2xvdXIgPSAiI0NDQ0NDQyIsIGxpbmV0eXBlID0gImRhc2hlZCINCiAgKQ0KDQojIHAgPC0gcCArDQojICAgc2NhbGVfeV9jb250aW51b3VzKA0KIyAgICAgbGltaXRzID0gYygtMTAsIDM1KSwNCiMgICAgIGJyZWFrcyA9IGMoMCwgMTUsIDMwKSwNCiMgICAgIGxhYmVscyA9IGMoMCwgMTUsIDMwKQ0KIyAgICkgKw0KIyAgIHNjYWxlX3hfY29udGludW91cygNCiMgICAgIGxpbWl0cyA9IGMoMCwgMTgwKSwNCiMgICAgIGJyZWFrcyA9IGMoMCwgNjAsIDEyMCwgMTgwKSwNCiMgICAgIGxhYmVscyA9IGMoMCwgNjAsIDEyMCwgMTgwKQ0KIyAgICkNCg0KIyBzZXQgZm9udCBzaXplIHRvIDExDQpwIDwtIHAgKw0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSkpDQoNCiMgYWRkIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGFuZCBkYXRhIHBvaW50cw0KcCA8LSBwICsgZ2VvbV9saW5lKCkNCg0KDQoNCiMgIyBzYXZlDQojIGlmIChzYXZlX3Bsb3RzKSB7DQojICAgZ2dzYXZlKA0KIyAgIHAsDQojICAgZmlsZW5hbWUgPSAiLi4vcGxvdHMvcGFwZXJfZmlncy9zcl8zMF90cmFpbmluZy5wZGYiLCBkZXZpY2UgPSAicGRmIiwNCiMgICBoZWlnaHQgPSA0LCB3aWR0aCA9IDYNCiMgICApDQojICAgfQ0KDQpnZ3Bsb3RseShwKQ0KDQojIHANCmBgYA0KDQojIyBQbG90IEVSUk9SIFNJWkUNCk5vdGU6IEJsdWVzID0gQWNjZWxlcmF0aW9uIFBlcnR1cmJhdGlvbnMNCmBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9Niwgb3V0LndpZHRoPSIxMDAlIn0NCiMgb3JpZ2luYWwgZXhwZXJpbWVudHMgb25seQ0KZGF0YV9wZXJfZ3JvdXAgPC0gb21uaWJ1c19kZiAlPiUNCiAgZmlsdGVyKGV4cF9sYWJlbCA9PSAib3JpZ2luYWxfZXhwcyIgfCBleHBfbGFiZWwgPT0gImN1cnZlZF9wYXRoIikgJT4lDQogIGdyb3VwX2J5KGV4cGVyaW1lbnQsIHRlc3RfdHlwZSwgdHJpYWxfbnVtKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIG1lYW5fZGV2aWF0aW9uID0gbWVhbihlcnJvcl9zaXplKSwNCiAgICBjaV9kZXZpYXRpb24gPSB2ZWN0b3JfY29uZmludChlcnJvcl9zaXplKSwNCiAgICAuZ3JvdXBzID0gImRyb3AiDQogICkNCg0KIyBzZXQgdXAgcGxvdA0KcCA8LSBkYXRhX3Blcl9ncm91cCAlPiUNCiAgZ2dwbG90KA0KICAgIGFlcygNCiAgICAgIHggPSB0cmlhbF9udW0sIHkgPSBtZWFuX2RldmlhdGlvbiwgY29sb3VyID0gZXhwZXJpbWVudA0KICAgICkNCiAgKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogICMgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArDQogIGxhYnMoDQogICAgeCA9ICJUcmlhbCBOdW1iZXIiLA0KICAgIHkgPSAiQWJzb2x1dGUgVGFyZ2V0IEVycm9yIChjbSkiDQogICkNCg0KIyBhZGQgaG9yaXpvbnRhbCBsaW5lcw0KcCA8LSBwICsNCiAgZ2VvbV9obGluZSgNCiAgICB5aW50ZXJjZXB0ID0gYygwLCA0MCksIGxpbmV3aWR0aCA9IDAuNCwNCiAgICBjb2xvdXIgPSAiI0NDQ0NDQyIsIGxpbmV0eXBlID0gInNvbGlkIg0KICApICsNCiAgZ2VvbV9obGluZSgNCiAgICB5aW50ZXJjZXB0ID0gYygyMCksIGxpbmV3aWR0aCA9IDAuNCwNCiAgICBjb2xvdXIgPSAiI0NDQ0NDQyIsIGxpbmV0eXBlID0gImRhc2hlZCINCiAgKQ0KDQojIHAgPC0gcCArDQojICAgc2NhbGVfeV9jb250aW51b3VzKA0KIyAgICAgbGltaXRzID0gYygtMTAsIDM1KSwNCiMgICAgIGJyZWFrcyA9IGMoMCwgMTUsIDMwKSwNCiMgICAgIGxhYmVscyA9IGMoMCwgMTUsIDMwKQ0KIyAgICkgKw0KIyAgIHNjYWxlX3hfY29udGludW91cygNCiMgICAgIGxpbWl0cyA9IGMoMCwgMTgwKSwNCiMgICAgIGJyZWFrcyA9IGMoMCwgNjAsIDEyMCwgMTgwKSwNCiMgICAgIGxhYmVscyA9IGMoMCwgNjAsIDEyMCwgMTgwKQ0KIyAgICkNCg0KIyBzZXQgZm9udCBzaXplIHRvIDExDQpwIDwtIHAgKw0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSkpDQoNCiMgYWRkIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGFuZCBkYXRhIHBvaW50cw0KcCA8LSBwICsgZ2VvbV9yaWJib24oDQogIGFlcygNCiAgICB5bWluID0gbWVhbl9kZXZpYXRpb24gLSBjaV9kZXZpYXRpb24sDQogICAgeW1heCA9IG1lYW5fZGV2aWF0aW9uICsgY2lfZGV2aWF0aW9uLA0KICAgIGZpbGwgPSBleHBlcmltZW50DQogICksDQogIGNvbG91ciA9IE5BLCBhbHBoYSA9IDAuMw0KKSArIGdlb21fbGluZSgpDQoNCiMgc2V0IGNvbG91ciBwYWxldHRlDQpwIDwtIHAgKw0KICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHBhbGxldGVfbGlzdCkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxsZXRlX2xpc3QpDQoNCg0KIyAjIHNhdmUNCiMgaWYgKHNhdmVfcGxvdHMpIHsNCiMgICBnZ3NhdmUoDQojICAgcCwNCiMgICBmaWxlbmFtZSA9ICIuLi9wbG90cy9wYXBlcl9maWdzL3NyXzMwX3RyYWluaW5nLnBkZiIsIGRldmljZSA9ICJwZGYiLA0KIyAgIGhlaWdodCA9IDQsIHdpZHRoID0gNg0KIyAgICkNCiMgICB9DQoNCmdncGxvdGx5KHApDQoNCiMgcA0KYGBgDQoNCnZpc2libGUgdnMgbm9uLXZpc2libGUgdGlsdCBkb2Vzbid0IGFmZmVjdCB0aGUgMTUtZGVncmVlIHJvdGF0aW9uIGNvbmRpdGlvbi4gQnV0IGFmZmVjdHMgYWxsIG90aGVyIGNvbmRpdGlvbnMuIFNvIDE1LWRlZ3JlZSByb3RhdGlvbg0KDQojIyMgVHJpYWwgc2V0cyBvZiBpbnRlcmVzdCBvbmx5DQpOb3RlOiBCbHVlcyA9IEFjY2VsZXJhdGlvbiBQZXJ0dXJiYXRpb25zDQpgYGB7ciwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTYsIG91dC53aWR0aD0iMTAwJSJ9DQojIGZpbHRlciBvdXQganVzdCB0aGUgdHJpYWxzIG9mIGludGVyZXN0DQpkYXRhX3Blcl9ncm91cCA8LSBkYXRhX3Blcl9ncm91cCAlPiUNCiAgZmlsdGVyKA0KICAgIHRlc3RfdHlwZSAhPSAib3RoZXIiDQogICkNCiMgYWRkIGEgZHVtbXkgY29sdW1uIHdpdGggcmVwZWF0aW5nIHNlcXVlbmNlDQojIE5PVEU6IHRoaXMgY2FuJ3QgYmUgY29tYmluZWQgd2l0aCBhYm92ZSBzaW5jZSB3ZSBhcmUgdXNpbmcgbnJvdw0KZGF0YV9wZXJfZ3JvdXAgPC0gZGF0YV9wZXJfZ3JvdXAgJT4lDQogIG11dGF0ZShkdW1teV94ID0gcmVwKDE6KG5yb3coZGF0YV9wZXJfZ3JvdXApIC8gTlVNX0VYUFMpLA0KICAgIGxlbmd0aC5vdXQgPSBucm93KGRhdGFfcGVyX2dyb3VwKQ0KICApKQ0KDQojIHNldCB1cCBwbG90DQpwIDwtIGRhdGFfcGVyX2dyb3VwICU+JQ0KICBnZ3Bsb3QoDQogICAgYWVzKA0KICAgICAgeCA9IGR1bW15X3gsIHkgPSBtZWFuX2RldmlhdGlvbiwgY29sb3VyID0gZXhwZXJpbWVudA0KICAgICkNCiAgKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogICMgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArDQogIGxhYnMoDQogICAgeCA9ICJUcmlhbCBOdW1iZXIiLA0KICAgIHkgPSAiQWJzb2x1dGUgVGFyZ2V0IEVycm9yIChjbSkiDQogICkNCg0KIyBhZGQgaG9yaXpvbnRhbCBsaW5lcw0KcCA8LSBwICsNCiAgZ2VvbV9obGluZSgNCiAgICB5aW50ZXJjZXB0ID0gYygwLCA0MCksIGxpbmV3aWR0aCA9IDAuNCwNCiAgICBjb2xvdXIgPSAiI0NDQ0NDQyIsIGxpbmV0eXBlID0gInNvbGlkIg0KICApICsNCiAgZ2VvbV9obGluZSgNCiAgICB5aW50ZXJjZXB0ID0gYygyMCksIGxpbmV3aWR0aCA9IDAuNCwNCiAgICBjb2xvdXIgPSAiI0NDQ0NDQyIsIGxpbmV0eXBlID0gImRhc2hlZCINCiAgKQ0KDQojIGFkZCBjb25maWRlbmNlIGludGVydmFscyBhbmQgZGF0YSBwb2ludHMNCmZvciAodW5pcXVlX3Rlc3RfdHlwZSBpbiB1bmlxdWUoZGF0YV9wZXJfZ3JvdXAkdGVzdF90eXBlKSkgew0KICAjIGdldCB0aGUgZGF0YSBmb3IgdGhpcyBibG9jaw0KICB0b19wbG90X2RhdGEgPC0gZmlsdGVyKGRhdGFfcGVyX2dyb3VwLCB0ZXN0X3R5cGUgPT0gdW5pcXVlX3Rlc3RfdHlwZSkNCg0KICBwIDwtIHAgKyBnZW9tX3JpYmJvbigNCiAgICBkYXRhID0gdG9fcGxvdF9kYXRhLA0KICAgIGFlcygNCiAgICAgIHltaW4gPSBtZWFuX2RldmlhdGlvbiAtIGNpX2RldmlhdGlvbiwNCiAgICAgIHltYXggPSBtZWFuX2RldmlhdGlvbiArIGNpX2RldmlhdGlvbiwNCiAgICAgIGZpbGwgPSBleHBlcmltZW50DQogICAgKSwgY29sb3VyID0gTkEsIGFscGhhID0gMC4zDQogICkgKyBnZW9tX2xpbmUoDQogICAgZGF0YSA9IHRvX3Bsb3RfZGF0YQ0KICApDQp9DQoNCiMgc2V0IGNvbG91ciBwYWxldHRlDQpwIDwtIHAgKw0KICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHBhbGxldGVfbGlzdCkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxsZXRlX2xpc3QpDQoNCmdncGxvdGx5KHApDQpgYGANCg0KDQoNCiMgQW5pbWF0ZWQgU3VyZmFjZSBGb2xsb3ctdXANCg0KIyMjIFBsb3QgQU5HVUxBUiBERVZJQVRJT05TIChoYW5kIGFuZ2xlcykNCmBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9Niwgb3V0LndpZHRoPSIxMDAlIn0NCiMgaXNvbGF0ZSBhbmltYXRlX3N1cmZhY2UgZXhwDQpkYXRhX3Blcl9ncm91cCA8LSBvbW5pYnVzX2RmICU+JQ0KICBmaWx0ZXIoZXhwX2xhYmVsID09ICJhbmltYXRlX3N1cmZhY2UiKSAlPiUNCiAgZ3JvdXBfYnkocHJpb3JfYW5pbSwgYmxvY2tfbnVtLCB0cmlhbF9udW1faW5fYmxvY2ssIHRyaWFsX251bSkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBtZWFuX2RldmlhdGlvbiA9IG1lYW4odGhyb3dfZGV2aWF0aW9uKSwNCiAgICBjaV9kZXZpYXRpb24gPSB2ZWN0b3JfY29uZmludCh0aHJvd19kZXZpYXRpb24pDQogICkNCg0KIyBvcmRlciB0aGUgZmFjdG9ycyBmb3IgYXNzaWduaW5nIGNvbG91ciBwYWxsZXRzDQpkYXRhX3Blcl9ncm91cCRwcmlvcl9hbmltIDwtIGZhY3RvcigNCiAgZGF0YV9wZXJfZ3JvdXAkcHJpb3JfYW5pbSwNCiAgbGV2ZWxzID0gYygNCiAgICAibm9uZSIsICJoYWxmX2FuaW0iLCAiZnVsbF9hbmltIg0KICApDQopDQoNCiMgc2V0IHVwIHBsb3QNCnAgPC0gZGF0YV9wZXJfZ3JvdXAgJT4lDQogIGdncGxvdCgNCiAgICBhZXMoDQogICAgICB4ID0gdHJpYWxfbnVtLCB5ID0gbWVhbl9kZXZpYXRpb24sDQogICAgICB5bWluID0gbWVhbl9kZXZpYXRpb24gLSBjaV9kZXZpYXRpb24sDQogICAgICB5bWF4ID0gbWVhbl9kZXZpYXRpb24gKyBjaV9kZXZpYXRpb24NCiAgICApDQogICkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICAjIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKw0KICBsYWJzKA0KICAgIHggPSAiVHJpYWwgTnVtYmVyIiwNCiAgICB5ID0gIlRocm93IEFuZ2xlICjCsCkiDQogICkNCg0KIyBhZGQgaG9yaXpvbnRhbCBsaW5lcw0KcCA8LSBwICsNCiAgZ2VvbV9obGluZSgNCiAgICB5aW50ZXJjZXB0ID0gYygwLCAtMzApLCBsaW5ld2lkdGggPSAwLjQsDQogICAgY29sb3VyID0gIiNDQ0NDQ0MiLCBsaW5ldHlwZSA9ICJzb2xpZCINCiAgKSArDQogIGdlb21faGxpbmUoDQogICAgeWludGVyY2VwdCA9IGMoLTE1KSwgbGluZXdpZHRoID0gMC40LA0KICAgIGNvbG91ciA9ICIjQ0NDQ0NDIiwgbGluZXR5cGUgPSAiZGFzaGVkIg0KICApDQoNCiMgcCA8LSBwICsNCiMgICBzY2FsZV95X2NvbnRpbnVvdXMoDQojICAgICBsaW1pdHMgPSBjKC0xMCwgMzUpLA0KIyAgICAgYnJlYWtzID0gYygwLCAxNSwgMzApLA0KIyAgICAgbGFiZWxzID0gYygwLCAxNSwgMzApDQojICAgKSArDQojICAgc2NhbGVfeF9jb250aW51b3VzKA0KIyAgICAgbGltaXRzID0gYygwLCAxODApLA0KIyAgICAgYnJlYWtzID0gYygwLCA2MCwgMTIwLCAxODApLA0KIyAgICAgbGFiZWxzID0gYygwLCA2MCwgMTIwLCAxODApDQojICAgKQ0KDQojIHNldCBmb250IHNpemUgdG8gMTENCnAgPC0gcCArDQogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSkNCg0KIyByZXBlYXQgZm9yIHByaW9yX2FuaW0gPT0gImhhbGYiLCAiZnVsbCIgYW5kICJ3YWl0Ig0KZm9yICh1bmlxdWVfcHJpb3JfYW5pbSBpbiB1bmlxdWUoZGF0YV9wZXJfZ3JvdXAkcHJpb3JfYW5pbSkpIHsNCiAgIyBnZXQgdGhlIGRhdGEgZm9yIHRoaXMgYmxvY2sNCiAgdG9fcGxvdF9kYXRhIDwtIGZpbHRlcihkYXRhX3Blcl9ncm91cCwgcHJpb3JfYW5pbSA9PSB1bmlxdWVfcHJpb3JfYW5pbSkNCiAgIyBsb29wIHRocm91Z2ggdGhlIHVuaXF1ZSBibG9ja3MgaW4gdG9fcGxvdF9kYXRhDQogIGZvciAoYmxvY2sgaW4gdW5pcXVlKHRvX3Bsb3RfZGF0YSRibG9ja19udW0pKSB7DQogICAgIyBnZXQgdGhlIGRhdGEgZm9yIHRoaXMgYmxvY2sNCiAgICBibG9ja19kYXRhIDwtIGZpbHRlcih0b19wbG90X2RhdGEsIGJsb2NrX251bSA9PSBibG9jaykNCiAgICAjIGFkZCB0aGUgZGF0YSwgdXNlIHRoZSBwYWxsZXRlX2xpc3QgdG8gZ2V0IHRoZSBjb2xvdXINCiAgICBwIDwtIHAgKyBnZW9tX3JpYmJvbigNCiAgICAgIGRhdGEgPSBibG9ja19kYXRhLA0KICAgICAgYWVzKGZpbGwgPSBwcmlvcl9hbmltKSwNCiAgICAgIGNvbG91ciA9IE5BLCBhbHBoYSA9IDAuMw0KICAgICkgKyBnZW9tX2xpbmUoDQogICAgICBkYXRhID0gYmxvY2tfZGF0YSwNCiAgICAgIGFlcyhjb2xvdXIgPSBwcmlvcl9hbmltKQ0KICAgICkNCiAgfQ0KfQ0KDQojIHNldCBjb2xvdXIgcGFsZXR0ZQ0KcCA8LSBwICsNCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBwYWxsZXRlX2xpc3QpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsbGV0ZV9saXN0KQ0KDQojICMgc2F2ZQ0KIyBpZiAoc2F2ZV9wbG90cykgew0KIyAgIGdnc2F2ZSgNCiMgICBwLA0KIyAgIGZpbGVuYW1lID0gIi4uL3Bsb3RzL3BhcGVyX2ZpZ3Mvc3JfMzBfdHJhaW5pbmcucGRmIiwgZGV2aWNlID0gInBkZiIsDQojICAgaGVpZ2h0ID0gNCwgd2lkdGggPSA2DQojICAgKQ0KIyAgIH0NCg0KZ2dwbG90bHkocCkNCiMgcA0KYGBgDQoNCiMjIyBXYXNob3V0IHRyaWFscyBhZnRlciBoYWxmIFZTIGZ1bGwgYW5pbWF0aW9ucw0KYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02LCBvdXQud2lkdGg9IjEwMCUifQ0KIyBmaXJzdCwgaXNvbGF0ZSB0aGUgZGF0YQ0KZGF0YSA8LSBvbW5pYnVzX2RmICU+JQ0KICBmaWx0ZXIoDQogICAgZXhwX2xhYmVsID09ICJhbmltYXRlX3N1cmZhY2UiLA0KICAgIGJhc2VsaW5lX2Jsb2NrID09IEZBTFNFLA0KICAgIHRlc3RfdHlwZSA9PSAid2FzaG91dF9hbmltIg0KICApDQoNCmRhdGFfcGVyX3BwdCA8LSBkYXRhICU+JQ0KICBncm91cF9ieShwcGlkLCBwcmlvcl9hbmltLCB0cmlhbF9udW1faW5fYmxvY2spICU+JQ0KICBzdW1tYXJpc2UoDQogICAgcHB0X21lYW5fZGV2aWF0aW9uID0gbWVkaWFuKHRocm93X2RldmlhdGlvbiksDQogICAgcHB0X2NpX2RldmlhdGlvbiA9IHZlY3Rvcl9jb25maW50KHRocm93X2RldmlhdGlvbiksDQogICAgbiA9IG4oKQ0KICApDQoNCmRhdGFfcGVyX2dyb3VwIDwtIGRhdGFfcGVyX3BwdCAlPiUNCiAgZ3JvdXBfYnkocHJpb3JfYW5pbSwgdHJpYWxfbnVtX2luX2Jsb2NrKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIG1lYW5fZGV2aWF0aW9uID0gbWVhbihwcHRfbWVhbl9kZXZpYXRpb24pLA0KICAgIGNpX2RldmlhdGlvbiA9IHZlY3Rvcl9jb25maW50KHBwdF9tZWFuX2RldmlhdGlvbiksDQogICAgbiA9IHN1bShuKQ0KICApDQoNCiMgc2V0IHVwIHBsb3QNCnAgPC0gZGF0YV9wZXJfZ3JvdXAgJT4lDQogIGdncGxvdCgNCiAgICBhZXMoDQogICAgICB4ID0gdHJpYWxfbnVtX2luX2Jsb2NrLCB5ID0gbWVhbl9kZXZpYXRpb24sDQogICAgICBjb2xvdXIgPSBwcmlvcl9hbmltLCBmaWxsID0gcHJpb3JfYW5pbQ0KICAgICkNCiAgKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogICMgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArDQogIGxhYnMoDQogICAgeCA9ICJUcmlhbCBOdW1iZXIgaW4gQmxvY2siLA0KICAgIHkgPSAiVGhyb3cgQW5nbGUgKMKwKSINCiAgKQ0KDQojIGFkZCBob3Jpem9udGFsIGxpbmVzDQpwIDwtIHAgKw0KICBnZW9tX2hsaW5lKA0KICAgIHlpbnRlcmNlcHQgPSBjKDAsIC0zMCksIGxpbmV3aWR0aCA9IDAuNCwNCiAgICBjb2xvdXIgPSAiI0NDQ0NDQyIsIGxpbmV0eXBlID0gInNvbGlkIg0KICApICsNCiAgZ2VvbV9obGluZSgNCiAgICB5aW50ZXJjZXB0ID0gYygtMTUpLCBsaW5ld2lkdGggPSAwLjQsDQogICAgY29sb3VyID0gIiNDQ0NDQ0MiLCBsaW5ldHlwZSA9ICJkYXNoZWQiDQogICkNCg0KIyBhZGQgZGF0YSBwb2ludHMNCnAgPC0gcCArIGdlb21fYmVlc3dhcm0oDQogIGRhdGEgPSBkYXRhX3Blcl9wcHQsDQogIGFlcygNCiAgICB5ID0gcHB0X21lYW5fZGV2aWF0aW9uLA0KICAgIGNvbG91ciA9IHByaW9yX2FuaW0NCiAgKSwNCiAgc2l6ZSA9IDEsIGRvZGdlLndpZHRoID0gMC41DQopICsgZ2VvbV9yaWJib24oDQogIGFlcygNCiAgICB5bWluID0gbWVhbl9kZXZpYXRpb24gLSBjaV9kZXZpYXRpb24sDQogICAgeW1heCA9IG1lYW5fZGV2aWF0aW9uICsgY2lfZGV2aWF0aW9uDQogICksDQogIGNvbG91ciA9IE5BLCBhbHBoYSA9IDAuMw0KKSArIGdlb21fbGluZSgpDQoNCiMgYWRkIHdhc2hvdXRfaW5pdCBmcm9tIHRoZSAzMC1kZWdyZWUgcm90YXRpb24gY29uZGl0aW9uDQpkYXRhX3Blcl9wcHRfMzAgPC0gb21uaWJ1c19kZiAlPiUNCiAgZmlsdGVyKA0KICAgIGV4cGVyaW1lbnQgJWluJSBjKCJyb3QzMF9jdWVkX3RpbHQiLCAicm90MzBfdW5jdWVkIiksDQogICAgdGVzdF90eXBlID09ICJ3YXNob3V0X2luaXQiDQogICkgJT4lICMgcmVuYW1lIHRoZSBleHBlcmltZW50IGNvbHVtbiB0byBwcmlvcl9hbmltDQogIG11dGF0ZShwcmlvcl9hbmltID0gZXhwZXJpbWVudCkNCg0KZGF0YV9wZXJfZ3JvdXBfMzAgPC0gZGF0YV9wZXJfcHB0XzMwICU+JQ0KICBncm91cF9ieShwcmlvcl9hbmltLCB0cmlhbF9udW1faW5fYmxvY2spICU+JQ0KICBzdW1tYXJpc2UoDQogICAgbWVhbl9kZXZpYXRpb24gPSBtZWFuKHRocm93X2RldmlhdGlvbiksDQogICAgY2lfZGV2aWF0aW9uID0gdmVjdG9yX2NvbmZpbnQodGhyb3dfZGV2aWF0aW9uKSwNCiAgICBuID0gbigpDQogICkNCg0KDQojIGFkZCBkYXRhIHBvaW50cw0KcCA8LSBwICsgZ2VvbV9iZWVzd2FybSgNCiAgZGF0YSA9IGRhdGFfcGVyX3BwdF8zMCwNCiAgYWVzKA0KICAgIHkgPSB0aHJvd19kZXZpYXRpb24sDQogICAgY29sb3VyID0gcHJpb3JfYW5pbQ0KICApLA0KICBzaXplID0gMSwgZG9kZ2Uud2lkdGggPSAwLjUNCikgKyBnZW9tX3JpYmJvbigNCiAgZGF0YSA9IGRhdGFfcGVyX2dyb3VwXzMwLA0KICBhZXMoDQogICAgeW1pbiA9IG1lYW5fZGV2aWF0aW9uIC0gY2lfZGV2aWF0aW9uLA0KICAgIHltYXggPSBtZWFuX2RldmlhdGlvbiArIGNpX2RldmlhdGlvbiwNCiAgICBmaWxsID0gcHJpb3JfYW5pbQ0KICApLA0KICBjb2xvdXIgPSBOQSwgYWxwaGEgPSAwLjMNCikgKyBnZW9tX2xpbmUoDQogIGRhdGEgPSBkYXRhX3Blcl9ncm91cF8zMCwNCiAgYWVzKA0KICAgIGNvbG91ciA9IHByaW9yX2FuaW0NCiAgKQ0KKQ0KDQojIHNldCBjb2xvdXIgcGFsZXR0ZQ0KcCA8LSBwICsNCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBwYWxsZXRlX2xpc3QpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsbGV0ZV9saXN0KQ0KDQpnZ3Bsb3RseShwKQ0KYGBgDQoNCg0KYGBge3IsIGluY2x1ZGU9RkFMU0V9DQojIyBFTVBUWQ0KYGBgDQoNCg0KIyBEZXByZWNhdGVkIChEb24ndCBSdW4pDQoNCiMjIFN1Y2Nlc3MgbWFuaWZvbGRzDQojIyMgV2l0aG91dCBhbnkgdGlsdHMNCmBgYHtyLCBmaWcud2lkdGg9OSwgZmlnLmhlaWdodD0yMH0NCiMgZ2dwbG90bHkocGxvdF9zdWNjZXNzX21hbmlmb2xkX25vX3RpbHQoKSkNCnBsb3Rfc3VjY2Vzc19tYW5pZm9sZF9ub190aWx0KCkNCmBgYA0KDQojIyMgV2l0aCB0aWx0IHByZXNlbnQNCmBgYHtyLCBmaWcud2lkdGg9OSwgZmlnLmhlaWdodD0yMH0NCmdncGxvdGx5KHBsb3Rfc3VjY2Vzc19tYW5pZm9sZF90aWx0KCkpDQpgYGANCg0KDQpgYGB7ciwgaW5jbHVkZT1GQUxTRX0NCk5VTEwNCmBgYA0KDQo=